/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package java.util.concurrent.locks;

import sun.misc.Unsafe;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Provides a framework for implementing blocking locks and related
 * synchronizers (semaphores, events, etc) that rely on
 * first-in-first-out (FIFO) wait queues.  This class is designed to
 * be a useful basis for most kinds of synchronizers that rely on a
 * single atomic {@code int} value to represent state. Subclasses
 * must define the protected methods that change this state, and which
 * define what that state means in terms of this object being acquired
 * or released.  Given these, the other methods in this class carry
 * out all queuing and blocking mechanics. Subclasses can maintain
 * other state fields, but only the atomically updated {@code int}
 * value manipulated using methods {@link #getState}, {@link
 * #setState} and {@link #compareAndSetState} is tracked with respect
 * to synchronization.
 *
 * <p>Subclasses should be defined as non-public internal helper
 * classes that are used to implement the synchronization properties
 * of their enclosing class.  Class
 * {@code AbstractQueuedSynchronizer} does not implement any
 * synchronization interface.  Instead it defines methods such as
 * {@link #acquireInterruptibly} that can be invoked as
 * appropriate by concrete locks and related synchronizers to
 * implement their public methods.
 *
 * <p>This class supports either or both a default <em>exclusive</em>
 * mode and a <em>shared</em> mode. When acquired in exclusive mode,
 * attempted acquires by other threads cannot succeed. Shared mode
 * acquires by multiple threads may (but need not) succeed. This class
 * does not &quot;understand&quot; these differences except in the
 * mechanical sense that when a shared mode acquire succeeds, the next
 * waiting thread (if one exists) must also determine whether it can
 * acquire as well. Threads waiting in the different modes share the
 * same FIFO queue. Usually, implementation subclasses support only
 * one of these modes, but both can come into play for example in a
 * {@link ReadWriteLock}. Subclasses that support only exclusive or
 * only shared modes need not define the methods supporting the unused mode.
 *
 * <p>This class defines a nested {@link ConditionObject} class that
 * can be used as a {@link Condition} implementation by subclasses
 * supporting exclusive mode for which method {@link
 * #isHeldExclusively} reports whether synchronization is exclusively
 * held with respect to the current thread, method {@link #release}
 * invoked with the current {@link #getState} value fully releases
 * this object, and {@link #acquire}, given this saved state value,
 * eventually restores this object to its previous acquired state.  No
 * {@code AbstractQueuedSynchronizer} method otherwise creates such a
 * condition, so if this constraint cannot be met, do not use it.  The
 * behavior of {@link ConditionObject} depends of course on the
 * semantics of its synchronizer implementation.
 *
 * <p>This class provides inspection, instrumentation, and monitoring
 * methods for the internal queue, as well as similar methods for
 * condition objects. These can be exported as desired into classes
 * using an {@code AbstractQueuedSynchronizer} for their
 * synchronization mechanics.
 *
 * <p>Serialization of this class stores only the underlying atomic
 * integer maintaining state, so deserialized objects have empty
 * thread queues. Typical subclasses requiring serializability will
 * define a {@code readObject} method that restores this to a known
 * initial state upon deserialization.
 *
 * <h3>Usage</h3>
 *
 * <p>To use this class as the basis of a synchronizer, redefine the
 * following methods, as applicable, by inspecting and/or modifying
 * the synchronization state using {@link #getState}, {@link
 * #setState} and/or {@link #compareAndSetState}:
 *
 * <ul>
 * <li> {@link #tryAcquire}
 * <li> {@link #tryRelease}
 * <li> {@link #tryAcquireShared}
 * <li> {@link #tryReleaseShared}
 * <li> {@link #isHeldExclusively}
 * </ul>
 * <p>
 * Each of these methods by default throws {@link
 * UnsupportedOperationException}.  Implementations of these methods
 * must be internally thread-safe, and should in general be short and
 * not block. Defining these methods is the <em>only</em> supported
 * means of using this class. All other methods are declared
 * {@code final} because they cannot be independently varied.
 *
 * <p>You may also find the inherited methods from {@link
 * AbstractOwnableSynchronizer} useful to keep track of the thread
 * owning an exclusive synchronizer.  You are encouraged to use them
 * -- this enables monitoring and diagnostic tools to assist users in
 * determining which threads hold locks.
 *
 * <p>Even though this class is based on an internal FIFO queue, it
 * does not automatically enforce FIFO acquisition policies.  The core
 * of exclusive synchronization takes the form:
 *
 * <pre>
 * Acquire:
 *     while (!tryAcquire(arg)) {
 *        <em>enqueue thread if it is not already queued</em>;
 *        <em>possibly block current thread</em>;
 *     }
 *
 * Release:
 *     if (tryRelease(arg))
 *        <em>unblock the first queued thread</em>;
 * </pre>
 * <p>
 * (Shared mode is similar but may involve cascading signals.)
 *
 * <p id="barging">Because checks in acquire are invoked before
 * enqueuing, a newly acquiring thread may <em>barge</em> ahead of
 * others that are blocked and queued.  However, you can, if desired,
 * define {@code tryAcquire} and/or {@code tryAcquireShared} to
 * disable barging by internally invoking one or more of the inspection
 * methods, thereby providing a <em>fair</em> FIFO acquisition order.
 * In particular, most fair synchronizers can define {@code tryAcquire}
 * to return {@code false} if {@link #hasQueuedPredecessors} (a method
 * specifically designed to be used by fair synchronizers) returns
 * {@code true}.  Other variations are possible.
 *
 * <p>Throughput and scalability are generally highest for the
 * default barging (also known as <em>greedy</em>,
 * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
 * While this is not guaranteed to be fair or starvation-free, earlier
 * queued threads are allowed to recontend before later queued
 * threads, and each recontention has an unbiased chance to succeed
 * against incoming threads.  Also, while acquires do not
 * &quot;spin&quot; in the usual sense, they may perform multiple
 * invocations of {@code tryAcquire} interspersed with other
 * computations before blocking.  This gives most of the benefits of
 * spins when exclusive synchronization is only briefly held, without
 * most of the liabilities when it isn't. If so desired, you can
 * augment this by preceding calls to acquire methods with
 * "fast-path" checks, possibly prechecking {@link #hasContended}
 * and/or {@link #hasQueuedThreads} to only do so if the synchronizer
 * is likely not to be contended.
 *
 * <p>This class provides an efficient and scalable basis for
 * synchronization in part by specializing its range of use to
 * synchronizers that can rely on {@code int} state, acquire, and
 * release parameters, and an internal FIFO wait queue. When this does
 * not suffice, you can build synchronizers from a lower level using
 * {@link java.util.concurrent.atomic atomic} classes, your own custom
 * {@link java.util.Queue} classes, and {@link LockSupport} blocking
 * support.
 *
 * <h3>Usage Examples</h3>
 *
 * <p>Here is a non-reentrant mutual exclusion lock class that uses
 * the value zero to represent the unlocked state, and one to
 * represent the locked state. While a non-reentrant lock
 * does not strictly require recording of the current owner
 * thread, this class does so anyway to make usage easier to monitor.
 * It also supports conditions and exposes
 * one of the instrumentation methods:
 *
 * <pre> {@code
 * class Mutex implements Lock, java.io.Serializable {
 *
 *   // Our internal helper class
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     // Reports whether in locked state
 *     protected boolean isHeldExclusively() {
 *       return getState() == 1;
 *     }
 *
 *     // Acquires the lock if state is zero
 *     public boolean tryAcquire(int acquires) {
 *       assert acquires == 1; // Otherwise unused
 *       if (compareAndSetState(0, 1)) {
 *         setExclusiveOwnerThread(Thread.currentThread());
 *         return true;
 *       }
 *       return false;
 *     }
 *
 *     // Releases the lock by setting state to zero
 *     protected boolean tryRelease(int releases) {
 *       assert releases == 1; // Otherwise unused
 *       if (getState() == 0) throw new IllegalMonitorStateException();
 *       setExclusiveOwnerThread(null);
 *       setState(0);
 *       return true;
 *     }
 *
 *     // Provides a Condition
 *     Condition newCondition() { return new ConditionObject(); }
 *
 *     // Deserializes properly
 *     private void readObject(ObjectInputStream s)
 *         throws IOException, ClassNotFoundException {
 *       s.defaultReadObject();
 *       setState(0); // reset to unlocked state
 *     }
 *   }
 *
 *   // The sync object does all the hard work. We just forward to it.
 *   private final Sync sync = new Sync();
 *
 *   public void lock()                { sync.acquire(1); }
 *   public boolean tryLock()          { return sync.tryAcquire(1); }
 *   public void unlock()              { sync.release(1); }
 *   public Condition newCondition()   { return sync.newCondition(); }
 *   public boolean isLocked()         { return sync.isHeldExclusively(); }
 *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
 *   public void lockInterruptibly() throws InterruptedException {
 *     sync.acquireInterruptibly(1);
 *   }
 *   public boolean tryLock(long timeout, TimeUnit unit)
 *       throws InterruptedException {
 *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
 *   }
 * }}</pre>
 *
 * <p>Here is a latch class that is like a
 * {@link java.util.concurrent.CountDownLatch CountDownLatch}
 * except that it only requires a single {@code signal} to
 * fire. Because a latch is non-exclusive, it uses the {@code shared}
 * acquire and release methods.
 *
 * <pre> {@code
 * class BooleanLatch {
 *
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     boolean isSignalled() { return getState() != 0; }
 *
 *     protected int tryAcquireShared(int ignore) {
 *       return isSignalled() ? 1 : -1;
 *     }
 *
 *     protected boolean tryReleaseShared(int ignore) {
 *       setState(1);
 *       return true;
 *     }
 *   }
 *
 *   private final Sync sync = new Sync();
 *   public boolean isSignalled() { return sync.isSignalled(); }
 *   public void signal()         { sync.releaseShared(1); }
 *   public void await() throws InterruptedException {
 *     sync.acquireSharedInterruptibly(1);
 *   }
 * }}</pre>
 *
 * @author Doug Lea
 * @since 1.5
 *
 * 1.AQS（AbstractQueuedSynchronizer，抽象队列同步器，简称同步器）
 *      AQS 是用来构建锁或者其他同步组件的基础框架。
 *      它使用一个volatile修饰的成员变量state来表示锁的状态（同步状态），通过内置FIFO队列来完成资源获取线程的排队工作。
 *  【备】：state 可以类比 synchronize 核心原理提到的 monitor监视器锁。
 * 2.在Object的监视器模型上，一个对象拥有一个同步队列和等待队列;
 *   并发包中的 Lock（更确切的说是AQS），拥有一个同步队列和多个等待队列。
 * 3.同步器的主要使用方式
 *      同步器的主要使用方式是继承。
 *      子类通过继承同步器并实现它的抽象方法来【管理 同步状态】。
 *      子类推荐被定义为自定义同步组件的静态内部类（在自定义同步组件中聚合AQS的子类）。
 * 4.同步组件：ReentrantLock、ReentrantReadWriteLock、CountDownLatch等。
 */
public abstract class AbstractQueuedSynchronizer
        extends AbstractOwnableSynchronizer
        implements java.io.Serializable {

    private static final long serialVersionUID = 7373984972572414691L;

    /**
     * Creates a new {@code AbstractQueuedSynchronizer} instance
     * with initial synchronization state of zero.
     */
    protected AbstractQueuedSynchronizer() {
    }

    /**
     * Wait queue node class.
     *
     * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
     * Hagersten) lock queue. CLH locks are normally used for
     * spinlocks.  We instead use them for blocking synchronizers, but
     * use the same basic tactic of holding some of the control
     * information about a thread in the predecessor of its node.  A
     * "status" field in each node keeps track of whether a thread
     * should block.  A node is signalled when its predecessor
     * releases.  Each node of the queue otherwise serves as a
     * specific-notification-style monitor holding a single waiting
     * thread. The status field does NOT control whether threads are
     * granted locks etc though.  A thread may try to acquire if it is
     * first in the queue. But being first does not guarantee success;
     * it only gives the right to contend.  So the currently released
     * contender thread may need to rewait.
     *
     * <p>To enqueue into a CLH lock, you atomically splice it in as new
     * tail. To dequeue, you just set the head field.
     * <pre>
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     * </pre>
     *
     * <p>Insertion into a CLH queue requires only a single atomic
     * operation on "tail", so there is a simple atomic point of
     * demarcation from unqueued to queued. Similarly, dequeuing
     * involves only updating the "head". However, it takes a bit
     * more work for nodes to determine who their successors are,
     * in part to deal with possible cancellation due to timeouts
     * and interrupts.
     *
     * <p>The "prev" links (not used in original CLH locks), are mainly
     * needed to handle cancellation. If a node is cancelled, its
     * successor is (normally) relinked to a non-cancelled
     * predecessor. For explanation of similar mechanics in the case
     * of spin locks, see the papers by Scott and Scherer at
     * http://www.cs.rochester.edu/u/scott/synchronization/
     *
     * <p>We also use "next" links to implement blocking mechanics.
     * The thread id for each node is kept in its own node, so a
     * predecessor signals the next node to wake up by traversing
     * next link to determine which thread it is.  Determination of
     * successor must avoid races with newly queued nodes to set
     * the "next" fields of their predecessors.  This is solved
     * when necessary by checking backwards from the atomically
     * updated "tail" when a node's successor appears to be null.
     * (Or, said differently, the next-links are an optimization
     * so that we don't usually need a backward scan.)
     *
     * <p>Cancellation introduces some conservatism to the basic
     * algorithms.  Since we must poll for cancellation of other
     * nodes, we can miss noticing whether a cancelled node is
     * ahead or behind us. This is dealt with by always unparking
     * successors upon cancellation, allowing them to stabilize on
     * a new predecessor, unless we can identify an uncancelled
     * predecessor who will carry this responsibility.
     *
     * <p>CLH queues need a dummy header node to get started. But
     * we don't create them on construction, because it would be wasted
     * effort if there is never contention. Instead, the node
     * is constructed and head and tail pointers are set upon first
     * contention.
     *
     * <p>Threads waiting on Conditions use the same nodes, but
     * use an additional link. Conditions only need to link nodes
     * in simple (non-concurrent) linked queues because they are
     * only accessed when exclusively held.  Upon await, a node is
     * inserted into a condition queue.  Upon signal, the node is
     * transferred to the main queue.  A special value of status
     * field is used to mark which queue a node is on.
     *
     * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
     * Scherer and Michael Scott, along with members of JSR-166
     * expert group, for helpful ideas, discussions, and critiques
     * on the design of this class.
     * <pre>
     * Node 是构成 同步队列（入口等待队列） 和 条件等待队列 的基础。
     *
     * 同步队列（入口等待队列）：当线程获取同步状态（锁资源）失败后就会被存放该队列中，当线程获取锁成功后，该线程会从同步队列中移除。
     * 条件队列（条件等待队列）：存放因调用 await()方法而等待的线程。
     * </pre>
     */
    static final class Node {
        /**
         * Marker to indicate a node is waiting in shared mode
         * 共享模式
         */
        static final Node SHARED = new Node();
        /**
         * Marker to indicate a node is waiting in exclusive mode
         * 独占模式
         */
        static final Node EXCLUSIVE = null;

        /**
         * waitStatus value to indicate thread has cancelled（线程已经被取消）
         * 因为超时或者中断，节点会被设置为[取消状态]，被取消的节点不会参与到同步状态 state 的竞争中，它会一直保持取消状态不会转变为其他状态。
         */
        static final int CANCELLED = 1;
        /**
         * waitStatus value to indicate successor's thread needs unparking
         * 后继结点的线程处于等待状态，而当前结点的线程如果释放了同步状态或者被取消，则会唤醒后继结点，使后继结点的线程能够运行。
         */
        static final int SIGNAL = -1;
        /**
         * waitStatus value to indicate thread is waiting on condition
         * 结点等待在 Condition【条件等待队列】 上（即，已经获取到同步状态[锁]的线程调用了 Condition 的 await()方法，就会将该线程加入到【条件等待队列】上），
         * 当其他线程对 Condition 调用了 signal() 后，该结点将会从【条件等待队列】转移到【入口等待队列/同步队列/阻塞队列】中。
         *
         * {@link ConditionObject#await()}
         * {@link ConditionObject#signal()}
         */
        static final int CONDITION = -2;
        /**
         * waitStatus value to indicate the next acquireShared should
         * unconditionally propagate
         */
        static final int PROPAGATE = -3;

        /**
         * Status field, taking on only the values:
         * ① SIGNAL:
         *      he successor of this node is (or will soon be) blocked (via park), so the current node must
         *  unpark its successor when it releases or cancels. To avoid races, acquire methods must
         *  first indicate they need a signal, then retry the atomic acquire, and then, on failure, block.
         * ② CANCELLED:
         *      In particular, a thread with cancelled node never again blocks.
         *      在同步队列中等待的线程由于超时或被中断，需要从同步队列中取消等待。节点进入该状态后不会再发生变化。
         * ③ CONDITION:
         *      It will not be used as a sync queue node until transferred, at which time the status
         *  will be set to 0. (Use of this value here has nothing to do with the other uses of the
         *  field, but simplifies mechanics.)
         *      节点在【条件等待队列】上，当其他线程调用了 Condition#signal() 方法后，会将该节点从条件等待队列转移到入口等待队列（同步队列）中，
         *  加入到对同步状态的获取中。
         * ④ PROPAGATE:
         *      A releaseShared should be propagated to other nodes. This is set (for head node only) in
         * doReleaseShared to ensure propagation continues, even if other operations have since intervened.
         * ⑤ 0: None of the above
         * <p>
         * The values are arranged numerically to simplify use.
         * Non-negative values mean that a node doesn't need to
         * signal. So, most code doesn't need to check for particular
         * values, just for sign.
         * <p>
         *
         * The field is initialized to 0 for normal sync nodes, and
         * CONDITION for condition nodes.  It is modified using CAS
         * (or when possible, unconditional volatile writes).
         * ①对于【同步队列/入口等待队列】而言，该字段的初始值为0（int基本类型的变量的初始值都是0）;
         * ②对于【条件等待队列】而言，该字段的初始值为 {@link #CONDITION}，通过构造器设置该字段值。
         */
        volatile int waitStatus;

        /**
         * Link to predecessor node that current node/thread relies on
         * for checking waitStatus. Assigned during enqueuing, and nulled
         * out (for sake of GC) only upon dequeuing.  Also, upon
         * cancellation of a predecessor, we short-circuit while
         * finding a non-cancelled one, which will always exist
         * because the head node is never cancelled: A node becomes
         * head only as a result of successful acquire. A
         * cancelled thread never succeeds in acquiring, and a thread only
         * cancels itself, not any other node.
         *
         * 前驱结点
         */
        volatile Node prev;

        /**
         * Link to the successor node that the current node/thread
         * unparks upon release. Assigned during enqueuing, adjusted
         * when bypassing cancelled predecessors, and nulled out (for
         * sake of GC) when dequeued.  The enq operation does not
         * assign next field of a predecessor until after attachment,
         * so seeing a null next field does not necessarily mean that
         * node is at end of queue. However, if a next field appears
         * to be null, we can scan prev's from the tail to
         * double-check.  The next field of cancelled nodes is set to
         * point to the node itself instead of null, to make life
         * easier for isOnSyncQueue.
         *
         * 后继结点
         */
        volatile Node next;

        /**
         * The thread that enqueued this node.  Initialized on
         * construction and nulled out after use.
         * 获取同步状态的线程。每个 Node 结点都包含着一个线程引用。
         */
        volatile Thread thread;

        /**
         * Link to next node waiting on condition, or the special
         * value SHARED.  Because condition queues are accessed only
         * when holding in exclusive mode, we just need a simple
         * linked queue to hold nodes while they are waiting on
         * conditions. They are then transferred to the queue to
         * re-acquire. And because conditions can only be exclusive,
         * we save a field by using special value to indicate shared
         * mode.
         *  1). 对于 入口等待队列 来说：该属性表示 节点类型（独占和共享）。
         *      ① 如果当前节点是独占式，那么这个字段就是EXCLUSIVE常量（即，null值）。
         *      ② 如果当前节点是共享的，那么这个字段将是SHARED常量。
         *  2). 对于 条件等待队列 来说：该属性表示 后继节点。
         */
        Node nextWaiter;

        /**
         * Returns true if node is waiting in shared mode.
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * Returns previous node, or throws NullPointerException if null.
         * Use when predecessor cannot be null.  The null check could
         * be elided, but is present to help the VM.
         *
         * @return the predecessor of this node
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker（ 用于建立初始头或SHARED标记 ）
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter（同步队列/入口等待队列 创建Node节点时调用）
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition（条件等待队列 创建Node节点时调用）
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

    /**
     * Head of the wait queue, lazily initialized.
     * Except for initialization, it is modified only via method setHead.
     * 除了初始化之外，只能通过setHead()方法修改head属性。
     *
     * head 相当于一个指针，指向 新创建空节点的地址 或 由线程节点转换为空节点的地址。
     * head 只有两种情况才会被赋值：
     *  ① 初始化时
     *      首先，调用Node类的空构造器创建一个头节点;
     *      然后，通过CAS的方式将新创建的头节点的地址赋给head属性（即，head指向头节点，head只是一个引用），方法：{@link #compareAndSetHead(Node)}。
     *      至于为什么要使用CAS来设置head，具体参见{@link #enq(Node)}方法中有说明。
     *  ② 同步队列中的线程节点里面的线程在成功获取到同步状态时
     *      直接调用方法{@link #setHead(Node)}，将线程节点转换为头节点（就是将用不到的属性置为null），并将head指向头节点。
     *      在这里为什么不用CAS的方式来设置head，具体参见 {@link #acquireQueued(Node, int)}
     * 所以说，在同步队列中，有两种节点：头节点 和 线程节点。
     * 假设，有5个线程获取同步状态都失败了，那么，将这5个线程封装为5个线程节点加入同步队列中后，同步队列中将会有6个节点（1个头节点 + 5个线程节点）。
     * Note: If head exists, its waitStatus is guaranteed not to be CANCELLED.
     */
    private transient volatile Node head;

    /**
     * Tail of the wait queue, lazily initialized.  Modified only via
     * method enq to add new wait node.
     */
    private transient volatile Node tail;

    /**
     * The synchronization state. 同步状态。
     */
    private volatile int state;

    /**
     * Returns the current value of synchronization state. 返回同步状态state的当前值。
     * This operation has memory semantics of a {@code volatile} read.
     *
     * @return current state value
     */
    protected final int getState() {
        return state;
    }

    /**
     * Sets the value of synchronization state.
     * This operation has memory semantics of a {@code volatile} write.
     *
     * @param newState the new state value
     */
    protected final void setState(int newState) {
        state = newState;
    }

    /**
     * <pre>
     * Atomically sets synchronization state to the given updated
     * value if the current state value equals the expected value.
     * This operation has memory semantics of a {@code volatile} read
     * and write.
     * 如果 当前同步状态的值 等于 期望值（expect），那么就将 同步状态的值 更新为给定的 更新值（update,即 new value）。
     * </pre>
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     * value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    // Queuing utilities

    /**
     * The number of nanoseconds for which it is faster to spin
     * rather than to use timed park. A rough estimate suffices
     * to improve responsiveness with very short timeouts.
     */
    static final long spinForTimeoutThreshold = 1000L;

    /**
     * Inserts node into queue, initializing if necessary. See picture above.
     * 将 Node节点 插入队列（入口等待队列），【必要时】需要初始化。
     * node节点的来源：①抢占锁失败的线程; ② 从【条件等待队列】上唤醒的线程节点。
     *
     * @param node the node to insert
     * @return node's predecessor 返回【入参 node 结点】的前驱结点
     */
    private Node enq(final Node node) {
        // 通过 “死循环” 确保结点被正确添加，最终将其设置为尾结点之后才能从该方法返回。
        for (; ; ) {
            // 新建变量 t，将指针指向【tail 指向的结点】（tail 指向的是 尾结点）
            // 即，tail 指向的是 尾结点，变量 t 指向的也是 尾结点。
            Node t = tail;
            // 如果【尾结点】为 null，则初始化（此时，为第一次循环）
            if (t == null) { // Must initialize
                /**
                 * 代码走到这一步，说明同步队列为空。
                 * ① 首先，创建一个【哨兵节点】（创建哨兵节点调用的是Node的无参构造器，创建出来的就只是一个空的Node节点）。
                 * ② 其次，将 创建的【哨兵节点】通过CAS的方式将其设置为head（头节点）。
                 *    Q: 为什么要通过CAS的方式设置head头节点？
                 *    A: 因为存在并发的情况。也就是说，可能存在有多个线程（假设有3个线程）在获取同步状态失败后要同时进入同步队列。
                 *       这种情况下，如果3个线程同时创建了3个哨兵节点，那么，又因为只会让其中一个哨兵节点成功设置为head，所以这里要使用CAS的方式。
                 *       而这3个【线程节点】则进入下一次循环，进入下次循环的线程节点也会通过CAS的方式加入同步队列尾部，直至所有线程节点成功加入，
                 *       即，else会执行3遍，每一遍只会有一个线程节点成功加入同步队列，也就是说，这3个线程中必然会有1个线程会将下面的
                 *       compareAndSetTail()执行3遍，而且只会在第3遍的时候成功。这让并发添加节点通过CAS变得“串行化”了。
                 *    【备】：注意区分 哨兵节点 和 线程节点。
                 */
                if (compareAndSetHead(new Node()))
                    // 尾指针 指向 哨兵结点（这个节点既是头节点，也是尾节点）。因为这个时候同步队列中只有一个空节点，所以head和tail都指向这个节点。
                    tail = head;
            } else {
                /**
                 * 代码走到这个分支的情况：
                 * ① 【队列】为空时，那么，在第一次 for 循环时必然走的是 if 分支（创建哨兵结点，设置头节点），
                 *     在第二次 for 循环时才会走到这个分支。
                 * ② 【队列】不为空，但是，存在并发的情况，所以，也要通过CAS的方式设置tail。
                 */
                // 将新结点的前驱结点指向队列中当前的尾结点。
                node.prev = t;
                // 将新节点加入到队列的尾结点，即，将 tail 指向【新节点 node】
                if (compareAndSetTail(t, node)) {
                    // 将 node 结点的地址 赋值给 曾经的尾结点的后继结点属性。
                    t.next = node;
                    return t;
                }
            }
        }
    }

    /**
     * Creates and enqueues node for current thread and given mode.
     * 为当前线程和给定模式创建结点并将其排队。
     * <pre>
     * 构造 Node 结点，并安全的（CAS）加入到【同步队列】的【尾部】。
     *
     * 【注意】：这里说的【同步队列】其实就是当前线程获取锁失败后加入的【阻塞队列】，
     *           其实跟 synchronized内置锁 一样，获取锁失败就会把线程构建成一个结点并加入到一个队列中。
     * </pre>
     * @param mode Node.EXCLUSIVE for exclusive 独占式, Node.SHARED for shared 共享式
     * @return the new node
     */
    private Node addWaiter(Node mode) {
        // 1- 构造 Node 结点，包含当前线程信息 和 结点模式（独占式 / 共享式）
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        // 新建变量 pred ，将指针指向 tail 指向的结点（tail 指向的是 尾结点）
        Node pred = tail;

        // 2- 如果 尾结点 不为空，将新建结点 node 插入【同步队列/入口等待队列】尾部。
        if (pred != null) {
            // 将新加入的结点 的 前驱结点 指向 尾结点。
            node.prev = pred;

            /**
             *      如果多个线程同时获取同步状态失败，都将会调用addWaiter()方法，也都有可能会执行到这里。
             *  所以，① 需要通过 CAS 的方式确保安全的设置当前结点为最新的尾结点;
             *      ② 只会有一个线程设置tail成功，其他线程都会失败，而设置tail失败的线程会继续向下执行enq()方法。
             *  这里，其实就是设置【同步队列】的属性 Node tail;（将 tail 指向当前结点）。
             */
            if (compareAndSetTail(pred, node)) {
                // 曾经的尾结点 的 后继结点 指向 当前结点。
                pred.next = node;
                // 返回 新构建的结点。
                return node;
            }
        }

        /**
         * 3- 代码走到这的条件：
         *      ① pred 为空（即，尾结点为空），则说明当前结点是第一个被加入到【同步队列/入口等待队列】中的结点。此时，执行入队操作。
         *      ② 上面的这一行代码【compareAndSetTail(pred, node)】失败，在并发的时候会发生的情况。
         */
        enq(node);
        return node;
    }

    /**
     * Sets head of queue to be node, thus dequeuing. Called only by
     * acquire methods.  Also nulls out unused fields for sake of GC
     * and to suppress unnecessary signals and traversals.
     * 将 node 设置为头（即，将 node 结点在内存中的地址赋值给 head，head 就是一个node对象的引用。）
     *
     * @param node the node
     */
    private void setHead(Node node) {
        // 将 node 线程节点的地址 赋给 head。
        head = node;
        // 将 node 节点（线程节点）用不到的属性置为 null。因为头节点只有 next 属性有用，其他啥用没有。
        node.thread = null;
        node.prev = null;
    }

    /**
     * Wakes up node's successor, if one exists.
     * 解除线程挂起状态：唤醒头结点的有效后继结点，如果有的话。
     *
     * {@link #shouldParkAfterFailedAcquire(Node, Node)}
     *
     * @param node the node
     */
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        // 获取【头结点】的 waitStatus（等待状态）
        int ws = node.waitStatus;
        // 头结点的状态 < 0
        if (ws < 0)
            // 通过 CAS 的方式将头结点的 waitStatus 设置为 0。即，清空头结点的 waitStatus 值。
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         *
         * 被唤醒的线程就在后继结点中，通常就是下一个结点。
         * 但是，如果下一个结点为空或者其状态为取消，则，
         * 从尾部开始向前查找，一直找到同步队列中【第一个】状态小于等于 0 的结点。
         */
        // 获取头结点的后继结点
        Node s = node.next;
        /**
         * 判断【头结点的后继结点是否为空】或者【其状态是否为取消状态（cancelled = 1）】
         * 因为可能会存在头结点的后继结点为 null，超时、被中断的情况。
         * 如果是，则需要将其移除，重新连接同步队列。
         */
        if (s == null || s.waitStatus > 0) {
            s = null;
            /**
             * 从【尾结点】开始向前查找，找到队列中【第一个】waitStatus 小于等于 0 的结点。
             * Q：这里为什么是从队列尾部开始向前查找不是 cancelled 的结点，而不是直接从 node.next 开始查找呢？伪代码如下：
             *    for (Node t = head; t != null; t = t.next){
             *        if(t.waitStatus <= 0){
             *            s = t;
             *            break;
             *        }
             *    }
             * A：问题的答案就在【结点加入队列】的方法中 {@link #addWaiter(Node)}，从中我们也能看到。
             *    首先会给 node.prev 赋值，再给 node.next 赋值。
             *    那么，问题就来了，当 node.next 还没有赋值的时候。此时，刚好又有一个线程恰好执行了当前的这个方法 {@link #unparkSuccessor(Node)}，
             *    这个时候，你怎么从前往后找，因为后继结点的指针还没有连接起来呢。
             */
            // 这里的目的就是要找到队列中第一个可用的线程。
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            // 解除线程挂起状态（即，唤醒头结点的后继结点，这里指的是第一个可用的节点）
            LockSupport.unpark(s.thread);
    }

    /**
     * Release action for shared mode -- signals successor and ensures
     * propagation. (Note: For exclusive mode, release just amounts
     * to calling unparkSuccessor of head if it needs signal.)
     *
     * 共享模式下释放结点 -- 向后继结点发送信号并确保传播。
     */
    private void doReleaseShared() {
        /*
         * Ensure that a release propagates, even if there are other
         * in-progress acquires/releases.  This proceeds in the usual
         * way of trying to unparkSuccessor of head if it needs
         * signal. But if it does not, status is set to PROPAGATE to
         * ensure that upon release, propagation continues.
         * Additionally, we must loop in case a new node is added
         * while we are doing this. Also, unlike other uses of
         * unparkSuccessor, we need to know if CAS to reset status
         * fails, if so rechecking.
         */
        for (; ; ) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    // 通过 CAS 的方式将头结点的 等待状态 由 signal 修改为 0。
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    // 只有将头结点的等待状态设置为 0 成功后，才能跳出循环，并唤醒头结点的下一个结点。
                    // 【注意】：这里唤醒的是【头结点】的【下一个结点】。
                    unparkSuccessor(h);
                } else if (ws == 0 &&
                        /**
                         * 当 ws（h.waitStatus）为 0 时，才会执行这个设置。
                         * 通过 CAS 的方式将头结点的 等待状态 由 0 修改为 propagate 状态。
                         */
                        !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

    /**
     * Sets head of queue, and checks if successor may be waiting
     * in shared mode, if so propagating if either propagate > 0 or
     * PROPAGATE status was set.
     *
     * @param node      the node 从调用方来看，这里的 node 只能是头结点的后继结点。
     * @param propagate the return value from a tryAcquireShared（以【共享模式】、【非阻塞式】获取【同步状态】的返回值）
     *
     * propagate 值的含义：
     *      ① propagate < 0 ：说明当前线程获取同步状态失败；
     *      ② propagate > 0 ：说明当前线程获取同步状态成功，还有剩余的同步状态可用于其他线程的获取；
     *      ③ propagate = 0 ：说明当前线程获取同步状态成功，但是没有剩余的同步状态可用于其他线程的获取。
     *
     */
    private void setHeadAndPropagate(Node node, int propagate) {
        // 记录【旧】的头结点，用于下面的 check
        Node h = head; // Record old head for check below
        // 将当前结点设置为头结点，即，将 head 指向 node 结点。
        setHead(node);
        /*
         * Try to signal next queued node if:
         * 如果出现以下情况，请尝试向队列中的下一个结点发送信号。
         *   Propagation was indicated by caller,
         *     or was recorded (as h.waitStatus either before
         *     or after setHead) by a previous operation
         *     (note: this uses sign-check of waitStatus because
         *      PROPAGATE status may transition to SIGNAL.)
         * and
         *   The next node is waiting in shared mode,
         *     or we don't know, because it appears null
         *
         * The conservatism in both of these checks may cause
         * unnecessary wake-ups, but only when there are multiple
         * racing acquires/releases, so most need signals now or soon
         * anyway.
         */
        /**
         * 1- 当 propagate > 0 时，说明当前线程获取同步状态成功，并且还有剩余的同步状态可用于其他线程的获取。
         *
         *    也就是说，当前线程获取同步状态成功后，由于还有剩余的同步状态可用于其他线程获取，
         *    那么就去通知在【入口等待队列/同步队列】中的其他线程，让他们也尝试获取同步状态。
         *
         *    想要让【同步队列/入口等待队列】中的其他线程获取到通知，那么就需要去调用 {@link #doReleaseShared()} 方法。
         *
         * 2- if 条件判断分析：
         *  1). h == null 和 (h = head) == null ：这两个条件是不可能成立的，因为当前方法的调用方在执行该方法之前都要去调用方法
         *      {@link #addWaiter(AbstractQueuedSynchronizer.Node)}
         *      入参为 Node.SHARED，这个方法会向【同步队列/入口等待队列】的尾部加入一个 node，也就是说【同步队列】中至少也会有一个 node 结点存在的。
         *  【从条件 ① 的分析来看，我们真正要关注的就是 propagate 和 waitStatus 了】
         *  2). propagate > 0：当该条件为真时（即，当前线程获取同步状态成功，并有剩余的同步状态可供其他线程获取），
         *      那么 if 中的其他条件也就不用判断了，然后根据 doReleaseShared 方法的判断条件进行释放。
         *
         *  在继续分析之前，先回顾下 waitStatus 的状态，如下：
         *      CANCELLED = 1：由于超时或中断，线程获取锁的请求被取消。结点变成该状态后不会再发生变化。
         *      SIGNAL = -1：表示线程已经准备好了，等待资源释放。
         *      CONDITION = -2：此结点当前在【条件等待队列 condition】中。
         *      PROPAGATE = -3：当线程处在 shared 情况下，该字段才会使用。
         *  这里不需要分析 cancelled 和 condition 两种状态了。
         *
         *  3). propagate > 0 不成立，h.waitStatus < 0 成立
         *    【注意】：这里的 h 指向的还是【旧】的头结点。
         *     Q1：什么情况下 h.waitStatus < 0 成立呢？
         *     A1：神奇的事情就来了，我们提前去看看 {@link #doReleaseShared()} 方法。
         *         从中可以看出要想让 h.waitStatus < 0 成立，只能执行【compareAndSetWaitStatus(h, 0, Node.PROPAGATE)】成功，
         *         也就是将其设置为 propagate = -3 的情况，而设置成功的前提是 h.waitStatus（头结点的等待状态）是 0。
         *     Q2：上面说要想让 h.waitStatus < 0 成立，只能是将其设置为 propagate = -3。那么新问题来了，在什么场景下，h.waitStatus 为 propagate？
         *     A2：大胆猜测下，当前线程执行到 h.waitStatus < 0 的判断之前，刚好有另外一个线程执行了 doReleaseShared() 方法，
         *         将 h.waitStatus 设置成了 propagate = -3。
         *  4). 前序条件都不成立，(h = head) == null || h.waitStatus < 0 成立
         *     【注意】：此时的 h 已经指向了【新】的头结点，因为在上一步setHead(node) 时已经替换了。
         *    SHTODO
         */
        if (propagate > 0 || h == null || h.waitStatus < 0 ||
                (h = head) == null || h.waitStatus < 0) {
            Node s = node.next;

            // 如果 当前结点的后继结点为空 或者 当前结点的后继结点为共享模式，则唤醒后继结点。
            // 这里当前结点的后继结点为空的意思指的是【同步队列】中只剩下 node 结点了，也就是说 只剩下【当前】（头结点）了。
            // 【注意】：代码执行到这一步 node 结点已经是队列中新的头结点了，在上一步setHead(node); 进行设置的。
            if (s == null || s.isShared())
                doReleaseShared();
        }
    }

    // Utilities for various versions of acquire

    /**
     * Cancels an ongoing attempt to acquire.
     * 将 node 节点 从【同步队列】上删除（顺带把node节点前面waitStatus为cancelled的节点也删除），并重新拼接整个队列。
     *
     * @param node the node
     */
    private void cancelAcquire(Node node) {
        // Ignore if node doesn't exist
        // 1- 忽略无效结点
        if (node == null)
            return;

        // 将结点关联的线程信息清空
        node.thread = null;

        // Skip cancelled predecessors
        // 2- 跳过状态为[取消状态]的所有前驱结点，最终找到一个有效前驱结点。
        //   并将当前结点的 prev 指向这个有效前驱结点。
        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;

        // predNext is the apparent node to unsplice. CASes below will
        // fail if not, in which case, we lost race vs another cancel
        // or signal, so no further action is necessary.
        // 3- 获取有效前驱结点的后继结点（如果 当前节点node 和 它的有效前驱节点pred 之间存在 取消状态的节点，那么，这里的 pred.next 指向的肯定就不是 当前节点node了）
        Node predNext = pred.next;

        // Can use unconditional write instead of CAS here.
        // After this atomic step, other Nodes can skip past us.
        // Before, we are free of interference from other threads.
        // 4- 将当前结点的状态设置为 cancelled（取消）
        node.waitStatus = Node.CANCELLED;

        /*
         * If we are the tail, remove ourselves.
         * 5-1 如果当前结点是尾结点，则直接从队列中删除自己
         * 这里的删除动作分为两步：
         *  1). compareAndSetTail(node, pred)
         *      ① 将 tail 指针指向 pred 结点（当前结点的有效前驱结点），即把当前结点（尾结点）从队列中删除。
         *      ② 通过 CAS 的方式确保安全的设置当前结点为最新的尾结点。
         *  2). compareAndSetNext(pred, predNext, null)
         *      将 pred.next 指向 null
         */
        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
            // 5-2 如果当前节点不是尾节点 或者 通过CAS方式设置新的尾节点tail失败。
            // If successor needs signal, try to set pred's next-link
            // so it will get one. Otherwise wake it up to propagate.
            int ws;
            // 1). 当前结点的有效前驱结点不是头结点，也就是说当前结点不是头结点的有效后继结点
            if (pred != head &&
                    // 2-1). 有效前驱结点的状态为 signal
                    ((ws = pred.waitStatus) == Node.SIGNAL ||
                            // 2-2). 如果有效前驱结点的状态不是 signal，则将其设置为 signal
                            (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                    // 3). 有效前驱结点的线程信息不为空
                    pred.thread != null) {
                // 获取当前结点的后继结点
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                    // 将当前结点的有效前驱结点的后继结点属性（pred.next） 指向 当前结点的后继结点next。即，pred.next = next;
                    compareAndSetNext(pred, predNext, next);
                    // TODO 这里为什么不继续执行 next.prev = pred 呢？不应该构成双向链表么？
            } else {
                /**
                 * 如果当前结点的有效前驱结点是【头结点】，或者不满足上述其他条件，
                 * 就唤醒当前结点的后继结点（因为当前线程节点的 waitStatus 已经被设置为 cancelled，所以说，这里本质上要唤醒的还是头节点的有效后继节点，毕竟当前节点已经没啥意义了）。
                 */
                unparkSuccessor(node);
            }

            node.next = node; // help GC
        }
    }

    /**
     * Checks and updates status for a node that failed to acquire.
     * Returns true if thread should block. This is the main signal
     * control in all acquire loops.  Requires that pred == node.prev.
     * 检查并更新 获取同步状态失败的结点（结点内部包含了线程信息）。
     * 如果线程需要被阻塞，则返回 true。
     *
     * 在线程获取同步状态失败后，线程并不是立马进行阻塞，而是需要检查该线程的状态。
     * 该方法就是【通过前驱结点来判断当前线程是否应该被阻塞】。
     *
     * Q: 为什么获取同步状态（锁）失败的线程不是立即被阻塞？
     * A: 因为Java线程是映射到操作系统的内核线程之上的（一一对应的关系，创建一个java线程，在操作系统中就会创建一个对应的内核线程）。
     *    所以说，如果要阻塞或唤醒一条线程，则需要操作系统帮忙完成，这样就会产生用户态和核心态的转换。
     *    而这种转换需要耗费很多CPU时间。尤其是对于代码特别简单的同步块，状态转换消耗的时间甚至比用户代码本身执行的时间还要长。
     *    这也是JDK1.5之前，我们说 synchronize 是重量级锁的关键所在。
     *
     * @param pred node's predecessor holding status
     * @param node the node
     * @return {@code true} if thread should block
     *
     * https://blog.csdn.net/anlian523/article/details/106448512
     *
     * {@link #unparkSuccessor(Node)}
     *
     * 调用这个方法的地方很多，看 {@link #acquireQueued(Node, int)} 就行了。
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        // 获取前驱结点的状态
        int ws = pred.waitStatus;
        // 1- 如果是 signal 状态（即，等待被占用的资源释放），直接返回 true（即，当前线程需要被阻塞）
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             *
             * 前驱结点的状态如果是 signal，就表示 闹钟已经设置好了，现在我（当前线程）就可以安心睡觉（阻塞）了。
             * 当前驱结点变成 head 时，并且 head 代表的线程 exclusiveOwnerThread 释放了锁，就会根据这个 signal 来唤醒自己。
             */
            return true;
        // 2- 如果 ws > 0，则说明是 cancelled（取消） 状态，表明该结点已经超时或者被中断了，需要从【同步队列/入口等待队列】中移除。
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             *
             * 循环判断，忽略（删除）状态为 cancelled 的结点，重新连接队列。
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
            /**
             * 代码走到这个分支，说明 ws 只能是 0 或者 propagate。
             * ws的值肯定不可能是condition，因为，如果是condition的话，那这个节点就应该在条件等待队列上。
             *
             * 将当前结点的前驱结点设置为 signal 状态，用于后续唤醒操作。
             *
             * Q1：这里为什么要将当前结点的前驱结点设置为 signal 状态呢？
             * A1：在释放锁的时候，在【唤醒头结点的后继结点】时会判断头结点的状态。
             * {@link #release(int)}
             *
             * Q2：为什么检测到 0 或者 propagate 后，一定要设置成 signal 呢？
             * A2：https://blog.csdn.net/anlian523/article/details/106448512
             *     标题：AQS深入理解 shouldParkAfterFailedAcquire源码分析 状态为0或PROPAGATE的情况分析
             */
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    /**
     * Convenience method to interrupt current thread.
     */
    static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

    /**
     * Convenience method to park and then check if interrupted
     * 将当前线程挂起，然后检查线程是否中断。
     *
     * @return {@code true} if interrupted
     */
    private final boolean parkAndCheckInterrupt() {
        /**
         * 将线程挂起，此时，程序就不会继续向下执行。
         *
         *      这个方法不会使线程状态变为 BLOCKED，而是变为 WAITING，
         *  从 {@link java.lang.Thread.State#WAITING} 字段的英文注释中可以看出来。
         *  当然，通过 jstack、Java visualVM 等工具  dump出来线程快照信息 也可以查看。
         */
        LockSupport.park(this);

        /**
         * 根据 park() 方法 API 描述，程序在下面三种情况时继续向下执行
         * ① 其他线程调用 unpark() 方法，该线程被 唤醒;
         *      Q: 被谁唤醒呢？
         *      A: 成功获取 同步状态（锁资源） 的线程在执行完用户代码后需要释放同步状态，此时会调用 {@link #release(int)}释放同步状态，
         *         release方法又会调用 {@link #unparkSuccessor(Node)} 方法去唤醒头节点的后继节点中的线程。
         * ② 其他线程将该线程 interrupt（中断）;
         * ③ 其他不合逻辑的返回
         */

        // 因为上述三种情况，程序执行到这个地方。
        // 返回当前线程是否被中断，并清空中断标志。如果被中断，则该方法会返回 true。
        return Thread.interrupted();
    }

    /*
     * Various flavors of acquire, varying in exclusive/shared and
     * control modes.  Each is mostly the same, but annoyingly
     * different.  Only a little bit of factoring is possible due to
     * interactions of exception mechanics (including ensuring that we
     * cancel if tryAcquire throws exception) and other control, at
     * least not without hurting performance too much.
     */

    /**
     * Acquires in exclusive uninterruptible mode for thread already in
     * queue. Used by condition wait methods as well as acquire.
     * 以【独占模式、不间断】获取已在【同步队列/阻塞队列/入口等待队列】中的线程。
     * 用于条件等待方法以及获取。
     *
     * @param node the node
     * @param arg  the acquire argument
     * @return {@code true} if interrupted while waiting.
     *      如果在阻塞期间被中断过则返回true，具体参见 {@link #parkAndCheckInterrupt()}。
     */
    final boolean acquireQueued(final Node node, int arg) {
        // 标识 获取资源是否失败。默认值为true，表示获取资源失败。
        boolean failed = true;
        try {
            // 当前线程的中断标志。默认值为false，表示线程在抢占锁资源的过程中没有被中断过。
            boolean interrupted = false;
            // "死循环（自旋）" 尝试获取锁，或者挂起。
            for (; ; ) {
                // 获取当前结点的前驱结点
                final Node p = node.predecessor();

                /**
                 * 1- 只有当前结点的前驱结点是头结点时(p == head 为真)，才会以独占模式尝试获取锁(同步状态state)[调用 tryAcquire()方法]
                 *    这也就是【哨兵结点】的作用了。哨兵结点 在方法 {@link #enq(Node)} 中被第一次初始化。
                 */
                if (p == head && tryAcquire(arg)) {
                    /**
                     * 获取同步状态成功后，将自己（线程节点）设置为头结点。
                     * Q: 这里设置head头节点为什么不使用CAS的方式？
                     * A: 因为在独占模式下，针对同一把锁，同一时刻只会有一个线程能够成功获取到同步状态（即，tryAcquire()方法返回true），
                     *    也就意味着，同一时刻只会有一个线程进入当前的这个if分支。所以，在设置head头节点的时候也就没必要通过CAS的方式。
                     */
                    setHead(node);
                    /*
                     * 1). 将 旧头节点的后继结点属性设置为空（注意这里仅仅只是把 p.next 置为空，并不是把 p 的下一个结点设置为空），方便 GC。
                     * 2). p 结点（即，原本的头结点）此时已经没有任何意义了，所以需要把 p.next 设置为空。
                     * 上一步setHead()方法已经把node.prev设置为null了，这里再把p.next设置为null，也就意味着原本的头节点已经处于游离状态了（就是没啥用了，可以被GC回收了）。
                     */
                    p.next = null; // help GC
                    failed = false;
                    // 返回中断标识，从自旋过程中退出。执行到这里就说明线程已经成功获取到锁了，接着可以去执行用户代码了。
                    return interrupted;
                }

                /**
                 * 2-
                 * 2-1. 走到这一步需要满足下面其中一个条件即可。
                 *     ① 当前结点的前驱结点不是头结点（p != head）时。
                 *     ② 【或者】当前结点的前驱结点是头结点，但是获取同步状态失败（tryAcquire()返回 false) 时。
                 *        Q：既然前驱节点已经是头节点了，那么为什么获取同步状态还会失败？
                 *        A：因为可能会有新的线程刚刚开始获取锁，也就是新的线程第一次调用 {@link Lock#lock()}方法。
                 * 2-2. shouldParkAfterFailedAcquire(p, node) 和 parkAndCheckInterrupt()
                 *      会将获取同步状态失败的线程挂起（阻塞），等待被唤醒 或者 中断。
                 * 1). shouldParkAfterFailedAcquire(p, node)
                 *     在线程获取同步状态失败后，线程并不是立马进行阻塞，而是需要检查该线程的状态。
                 *     该方法就是【通过前驱结点来判断当前线程是否应该被阻塞】。
                 *     Q: 为什么获取同步状态（锁）失败的线程不是立即被阻塞？
                 *     A: 因为Java线程是映射到操作系统的内核线程之上的（一一对应的关系，创建一个java线程，在操作系统中就会创建一个对应的内核线程）。
                 *        所以说，如果要阻塞或唤醒一条线程，则需要操作系统帮忙完成，这样就会产生用户态和核心态的转换。
                 *        而这种转换需要耗费很多CPU时间。尤其是对于代码特别简单的同步块，状态转换消耗的时间甚至比用户代码本身执行的时间还要长。
                 *        这也是JDK1.5之前，我们说 synchronize 是重量级锁的关键所在。
                 * 2). 依据方法 shouldParkAfterFailedAcquire(p, node) 的返回值，有两种情况
                 *     ① 如果返回 true，则说明当前线程应该被阻塞。
                 *       调用方法 parkAndCheckInterrupt()：将当前线程挂起。直到调用 {@link LockSupport#unpark(Thread)}方法唤醒当前线程 或者 被中断。
                 *     ② 如果返回 false，那么继续下一次 for 循环，
                 *       再次尝试获取同步状态【if (p == head && tryAcquire(arg))】
                 *
                 * // 当挂起的线程被唤醒或被中断时，会继续当前的 for 死循环，等待抢占同步状态。
                 * 【备】：即便是线程被中断，也不会从同步队列中移出，而是继续下次循环。
                 */
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    /**
                     * 与 {@link #doAcquireInterruptibly(int)} 的区别就在这里。
                     *
                     * 代码走到这一行，说明 parkAndCheckInterrupt() 方法返回true，意味着线程已经被中断。
                     * 那又怎样？就是不抛出异常，继续下一次循环，直到抢占锁资源成功。
                     * 本质上就是对 Thread#interrupt()方法发出的中断通知，直接选择无视。
                     * 这行代码就是【不可中断锁】的要点（不可中断：指的是，线程在获取锁资源的过程中，针对Thread#interrupt()发出的中断通知，选择置之不理。）
                     */
                    interrupted = true;
            }

            /**
             * 上面的 for 自旋，我们在这里假设两种场景。
             * 1. 当前结点 node 的前驱结点不是头结点
             * 1.1 第一次 for 循环
             *          调用方法 shouldParkAfterFailedAcquire 判断是否需要阻塞（挂起）【通过前驱结点来判断当前线程是否应该被阻塞】。
             *      在方法 shouldParkAfterFailedAcquire 内部就会走到最后一个 else 中（即，node 结点的前驱结点的 waitStatus
             *      为 0 的分支），这个分支内部又会将 node 结点的前驱结点的 waitStatus 修改为 signal，
             *      并返回 false，进入下一次 for 循环。
             *
             *      Q：在方法 shouldParkAfterFailedAcquire 中为什么会走到最后一个 else 分支？
             *      A：因为在第一次调用 shouldParkAfterFailedAcquire 方法之前，node 结点是新创建出来的，
             *          在执行完方法 {@link #addWaiter(Node)} 后，node 便成为新的队尾，那么也就意味着 node 结点的
             *          前驱结点是原来旧的队尾，而原来旧的队尾的状态肯定还是 0（也就是默认初始化的值）。
             * 1.2 第二次 for 循环
             *          再次调用方法 shouldParkAfterFailedAcquire 判断是否需要阻塞（挂起）。
             *      此时，在方法 shouldParkAfterFailedAcquire 内部就会走到第一个 if 分支（即，node 结点的前驱结点的 waitStatus
             *      为 signal 的分支），此时，直接返回 true。接着执行方法 parkAndCheckInterrupt 将当前线程挂起。
             *
             *      Q：此次在方法 shouldParkAfterFailedAcquire 中为什么会走第一个 if 分支？
             *      A：因为在第一次 for 循环结束后，也就是第一次执行完 shouldParkAfterFailedAcquire 方法后，已经将 node 结点的
             *          前驱结点的 waitStatus 修改为了 signal。
             * 2. 当前结点 node 的前驱结点是头结点
             *    这里不说 tryAcquire 成功的逻辑，这里也不按照上面一种情况来说明。
             * 2.1 第一次 for 循环
             *      tryAcquire 失败（即，获取同步状态[锁]失败）。
             *      方法 shouldParkAfterFailedAcquire：
             *          我们假设执行到第一个分支（即，当前结点 node 的前驱结点 head 的 waitStatus 为 signal），并且返回 true。
             *          接着执行方法 parkAndCheckInterrupt 将当前线程挂起。
             *
             *          当某一个线程在执行 {@link #release(int)} 方法时，如果 tryRelease 成功（即，释放同步状态[锁]成功）后，
             *      只要满足【头结点不为空，且头结点的 waitStatus 不为 0】，即可调用方法 {@link #unparkSuccessor(Node)}
             *      唤醒【入口等待队列】中头结点的后继结点。
             *          在方法 unparkSuccessor 中会判断头结点的 waitStatus 是否小于 0，如果小于 0，
             *      则将头结点的 waitStatus 设置为 初始状态 0。
             * 2.2 第二次 for 循环
             *      tryAcquire 同样失败（即，获取同步状态[锁]失败）。
             *      方法 shouldParkAfterFailedAcquire：
             *              此时，会执行最后一个 else 分支（因为在第一次 for 循环中，在 unparkSuccessor 方法中
             *          将头结点的 waitStatus 设置为 0 了），这个分支内部又会将 node 结点的前驱结点的 waitStatus 修改为 signal，
             *          并返回 false，进入下一次 for 循环。
             * 2.3 第三次 for 循环
             *      tryAcquire 同样失败（即，获取同步状态[锁]失败）。
             *      方法 shouldParkAfterFailedAcquire：
             *              此时，会执行第一个 if 分支（即，node 结点的前驱结点的 waitStatus 为 signal 的分支），
             *          直接返回 true。接着执行方法 parkAndCheckInterrupt 将当前线程挂起。
             * 接下来，又执行 unparkSuccessor 方法，又回到【第一次 for 循环】的情况。
             */
        } finally {
            /**
             * finally 代码块是肯定会被执行的（当然，程序所在线程被kill 或 电脑被砸了 的情况除外）。
             * 不管是成功获取到锁资源了，还是在获取锁资源的过程中出现异常了，都会执行finally代码块。
             * ① 当线程成功获取到锁资源时，failed 为 false;
             * ② 当线程在获取锁资源的过程中出现异常，failed 就还是初始值 true。
             */
            if (failed) {
                // 当线程在获取锁资源的过程中出现异常的话，就调用方法 cancelAcquire()，取消线程获取锁的请求。
                cancelAcquire(node);
            }
        }
    }

    /**
     * Acquires in exclusive interruptible mode.
     * 以【独占模式】、【不间断】获取已在【同步队列/阻塞队列/入口等待队列】中的线程，【可中断模式】。
     *
     * {@link AbstractQueuedSynchronizer#acquireQueued(java.util.concurrent.locks.AbstractQueuedSynchronizer.Node, int)}
     *
     * @param arg the acquire argument
     */
    private void doAcquireInterruptibly(int arg)
            throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            // "死循环" 尝试获取锁，或者挂起。
            for (; ; ) {
                // 获取当前结点的前驱结点
                final Node p = node.predecessor();
                // 1- 当前结点的前驱结点为【头结点】时，才会尝试去获取同步状态（以【非阻塞】、【独占模式】去获取）。
                if (p == head && tryAcquire(arg)) {
                    // 获取同步状态成功后，将当前结点设置为头结点。即，将 head 指向 node 结点（head 中存放的就是 node 结点在内存中的地址）
                    setHead(node);
                    // 将头结点的后继结点置为空（注意这里仅仅只是把 p.next 置为空，并不是把 p 的下一个结点设置为空）
                    p.next = null; // help GC
                    failed = false;
                    return;
                }

                /*
                 * 2-
                 * 1). 走到这一步需要满足下面其中一个条件即可。
                 *     ① 当前结点的前驱结点不是头结点（p != head）时。
                 *     ② 【或者】当前结点的前驱结点是头结点，但是获取同步状态失败（tryAcquire()返回 false) 时。
                 * 2). shouldParkAfterFailedAcquire(p, node) 和 parkAndCheckInterrupt() 会将获取同步状态失败的线程挂起，
                 *     等待被唤醒 或者 中断。
                 */
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    /**
                     * 与 {@link #acquireQueued(AbstractQueuedSynchronizer.Node, int)} 区别就在这里了。
                     *
                     * 代码走到这里说明 parkAndCheckInterrupt()方法也返回true，说明线程已经被中断了，直接抛出 InterruptedException。
                     */
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * Acquires in exclusive timed mode.
     * 以 【独占模式】、【阻塞式】、超时限制 获取同步状态。
     *
     * @param arg          the acquire argument
     * @param nanosTimeout max wait time 最大等待时间
     * @return {@code true} if acquired
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        // 计算超时截止时间 = 当前时间 + 最大等待时间
        // 也即是说，从现在开始一直到 deadline，当前线程还是没有获取到同步状态的话，那就给老子死。
        final long deadline = System.nanoTime() + nanosTimeout;
        // 以 【独占模式】 新增 node 并加入到【同步队列】的尾部
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            // 自旋
            for (; ; ) {
                // 获取当前结点的前驱结点
                final Node p = node.predecessor();

                // 1-1 如果当前结点的前驱结点为头结点，则尝试获取同步状态（这里也是通过 CAS 的方式进行获取）。
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }

                /*
                 * 1-2
                 * 1). 走到这一步需要满足下面其中一个条件即可。
                 *     ① 当前结点的前驱结点不是头结点（p != head）时。
                 *     ② 【或者】当前结点的前驱结点是头结点，但是获取同步状态失败（tryAcquire()返回 false) 时。
                 */

                // 重新计算超时截止时间 = 超时截止时间 - 当前时间，其实就是还剩多少时间。
                nanosTimeout = deadline - System.nanoTime();
                // 如果超时（大限将至），直接返回 false
                if (nanosTimeout <= 0L)
                    return false;
                // 如果没有超时，则等待 nanosTimeout 纳秒
                // 【注意】：该线程会直接从 LockSupport.parkNanos 中返回。
                if (shouldParkAfterFailedAcquire(p, node) &&
                        // 判断超时时间是否大于 1000
                        nanosTimeout > spinForTimeoutThreshold)
                    // 挂起线程 nanosTimeout 长时间，时间到就自动返回
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * Acquires in shared uninterruptible mode.
     * 以【共享模式、不间断】获取已在【同步队列/阻塞队列/入口等待队列】中的线程。
     *
     * @param arg the acquire argument
     */
    private void doAcquireShared(int arg) {
        // 创建【共享模式（shared）】的结点，并将其加入到【同步队列/阻塞队列/入口等待队列】的尾部。
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            boolean interrupted = false;
            // 进入【自旋】
            for (; ; ) {
                // 获取当前结点的前驱结点
                final Node p = node.predecessor();
                // 1-1 判断当前结点的前驱结点是否为头结点
                if (p == head) {
                    // 如果当前结点的前驱结点为头结点，则以【共享模式】、【非阻塞式】获取【同步状态】。
                    /*
                     * r 返回值的含义：
                     *      ① r < 0 ：说明当前线程获取同步状态失败；
                     *      ② r > 0 ：说明当前线程获取同步状态成功，还有剩余的同步状态可用于其他线程的获取；
                     *      ③ r = 0 ：说明当前线程获取同步状态成功，但是没有剩余的同步状态可用于其他线程的获取。
                     */
                    int r = tryAcquireShared(arg);
                    // 如果返回结果大于等于 0，则说明获取同步状态成功。
                    if (r >= 0) {
                        /**
                         * 【与 {@link #acquireQueued(AbstractQueuedSynchronizer.Node, int)} 的区别就在这里】。
                         *
                         * 设置头结点 并 传播（propagate[r]）。
                         */
                        setHeadAndPropagate(node, r);
                        // 将头结点的后继结点设置为空（注意这里仅仅只是把 p.next 置为空，并不是把 p 的下一个结点设置为空）
                        p.next = null; // help GC
                        if (interrupted)
                            selfInterrupt();
                        failed = false;
                        return;
                    }
                }

                /**
                 * 1-2 解释参考 {@link #acquireQueued(Node, int)}
                 */
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * Acquires in shared interruptible mode.
     *
     * @param arg the acquire argument
     */
    private void doAcquireSharedInterruptibly(int arg)
            throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            // 自旋
            for (; ; ) {
                // 获取当前结点的前驱结点
                final Node p = node.predecessor();
                // 1- 判断当前结点的前驱结点是否为头结点
                if (p == head) {
                    // 如果当前结点的前驱结点为头结点，则以【共享模式】、【非阻塞式】获取【同步状态（锁）】。
                    /*
                     * r 返回值的含义：
                     *      ① r < 0 ：说明当前线程获取同步状态失败；
                     *      ② r > 0 ：说明当前线程获取同步状态成功，还有剩余的同步状态可用于其他线程的获取；
                     *      ③ r = 0 ：说明当前线程获取同步状态成功，但是没有剩余的同步状态可用于其他线程的获取。
                     */
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        /**
                         * 【与 {@link #acquireQueued(AbstractQueuedSynchronizer.Node, int)} 的区别就在这里】。
                         *
                         * 设置头结点 并 传播（propagate）。
                         */
                        setHeadAndPropagate(node, r);
                        /*
                         * 将头结点的后继结点设置为空（注意这里仅仅只是把 p.next 置为空，并不是把 p 的下一个结点设置为空）；
                         */
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }

                /**
                 * 2-
                 * 解释参考 {@link #acquireQueued(Node, int)}
                 */
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * Acquires in shared timed mode.
     *
     * @param arg          the acquire argument
     * @param nanosTimeout max wait time
     * @return {@code true} if acquired
     */
    private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (; ; ) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return true;
                    }
                }
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
                        nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    // Main exported methods

    /**
     * Attempts to acquire in exclusive mode. This method should query
     * if the state of the object permits it to be acquired in the
     * exclusive mode, and if so to acquire it.
     *
     * <p>This method is always invoked by the thread performing
     * acquire.  If this method reports failure, the acquire method
     * may queue the thread, if it is not already queued, until it is
     * signalled by a release from some other thread. This can be used
     * to implement method {@link Lock#tryLock()}.
     *
     * <p>The default
     * implementation throws {@link UnsupportedOperationException}.
     *
     * 【独占式】、【非阻塞式】 获取同步状态。
     *
     * @param arg the acquire argument. This value is always the one
     *            passed to an acquire method, or is the value saved on entry
     *            to a condition wait.  The value is otherwise uninterpreted
     *            and can represent anything you like.
     * @return {@code true} if successful. Upon success, this object has
     * been acquired.
     * @throws IllegalMonitorStateException  if acquiring would place this
     *                                       synchronizer in an illegal state. This exception must be
     *                                       thrown in a consistent fashion for synchronization to work
     *                                       correctly.
     * @throws UnsupportedOperationException if exclusive mode is not supported
     *                                       <p>
     */
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Attempts to set the state to reflect a release in exclusive
     * mode.
     *
     * <p>This method is always invoked by the thread performing release.
     *
     * <p>The default implementation throws
     * {@link UnsupportedOperationException}.
     *
     * @param arg the release argument. This value is always the one
     *            passed to a release method, or the current state value upon
     *            entry to a condition wait.  The value is otherwise
     *            uninterpreted and can represent anything you like.
     * @return {@code true} if this object is now in a fully released
     * state, so that any waiting threads may attempt to acquire;
     * and {@code false} otherwise.
     * @throws IllegalMonitorStateException  if releasing would place this
     *                                       synchronizer in an illegal state. This exception must be
     *                                       thrown in a consistent fashion for synchronization to work
     *                                       correctly.
     * @throws UnsupportedOperationException if exclusive mode is not supported
     */
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Attempts to acquire in shared mode. This method should query if
     * the state of the object permits it to be acquired in the shared
     * mode, and if so to acquire it.
     *
     * <p>This method is always invoked by the thread performing
     * acquire.  If this method reports failure, the acquire method
     * may queue the thread, if it is not already queued, until it is
     * signalled by a release from some other thread.
     *
     * <p>The default implementation throws {@link
     * UnsupportedOperationException}.
     *
     * @param arg the acquire argument. This value is always the one
     *            passed to an acquire method, or is the value saved on entry
     *            to a condition wait.  The value is otherwise uninterpreted
     *            and can represent anything you like.
     * @return a negative value on failure; zero if acquisition in shared
     * mode succeeded but no subsequent shared-mode acquire can
     * succeed; and a positive value if acquisition in shared
     * mode succeeded and subsequent shared-mode acquires might
     * also succeed, in which case a subsequent waiting thread
     * must check availability. (Support for three different
     * return values enables this method to be used in contexts
     * where acquires only sometimes act exclusively.)  Upon
     * success, this object has been acquired.
     * @throws IllegalMonitorStateException  if acquiring would place this
     *                                       synchronizer in an illegal state. This exception must be
     *                                       thrown in a consistent fashion for synchronization to work
     *                                       correctly.
     * @throws UnsupportedOperationException if shared mode is not supported
     * @return int ：AQS 的实现类（自定义同步器）中 返回值 value 的三种情况
     *      ① value < 0 ：说明当前线程获取同步状态失败；
     *      ② value > 0 ：说明当前线程获取同步状态成功，还有剩余的同步状态可以让其他线程的获取；
     *      ③ value = 0 ：说明当前线程获取同步状态成功，但是没有剩余的同步状态可以让其他线程的获取。
     */
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Attempts to set the state to reflect a release in shared mode.
     *
     * <p>This method is always invoked by the thread performing release.
     *
     * <p>The default implementation throws
     * {@link UnsupportedOperationException}.
     *
     * @param arg the release argument. This value is always the one
     *            passed to a release method, or the current state value upon
     *            entry to a condition wait.  The value is otherwise
     *            uninterpreted and can represent anything you like.
     * @return {@code true} if this release of shared mode may permit a
     * waiting acquire (shared or exclusive) to succeed; and
     * {@code false} otherwise
     * @throws IllegalMonitorStateException  if releasing would place this
     *                                       synchronizer in an illegal state. This exception must be
     *                                       thrown in a consistent fashion for synchronization to work
     *                                       correctly.
     * @throws UnsupportedOperationException if shared mode is not supported
     */
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns {@code true} if synchronization is held exclusively with
     * respect to the current (calling) thread.  This method is invoked
     * upon each call to a non-waiting {@link ConditionObject} method.
     * (Waiting methods instead invoke {@link #release}.)
     *
     * <p>The default implementation throws {@link
     * UnsupportedOperationException}. This method is invoked
     * internally only within {@link ConditionObject} methods, so need
     * not be defined if conditions are not used.
     *
     * @return {@code true} if synchronization is held exclusively;
     * {@code false} otherwise
     * @throws UnsupportedOperationException if conditions are not supported
     */
    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

    /**
     * Acquires in exclusive mode, ignoring interrupts.  Implemented
     * by invoking at least once {@link #tryAcquire},
     * returning on success.  Otherwise the thread is queued, possibly
     * repeatedly blocking and unblocking, invoking {@link
     * #tryAcquire} until success.  This method can be used
     * to implement method {@link Lock#lock}.
     *
     * 1). 以【独占模式】、【阻塞式】获取同步状态。
     * 2). 该方法对中断不响应，即，
     *     由于线程获取 同步状态 失败 而加入到【同步队列/阻塞队列/入口等待队列】中，对线程进行中断操作后，
     *     该线程依然会处于 同步队列（阻塞队列/入口等待队列）中 等待着获取同步状态。
     * {@link #acquireInterruptibly(int)}
     *
     * @param arg the acquire argument.  This value is conveyed to
     *            {@link #tryAcquire} but is otherwise uninterpreted and
     *            can represent anything you like.
     */
    public final void acquire(int arg) {
        /**
         * <pre>
         *     1- tryAcquire()方法
         *        调用 AQS 实现类（自定义同步器）重写的 tryAcquire() 方法【以（非阻塞式）获取同步状态】。
         *        获取成功则设置锁状态并返回 true，否则返回 false。
         *
         *        从这里也可以看出来，即使是阻塞式获取同步状态，在第一步的时候还是 尝试通过非阻塞式的去获取同步状态。
         *        如果获取锁失败（tryAcquire()方法返回 false），则继续后续的步骤。
         *     2- 针对获取同步状态失败的线程的处理逻辑
         *     2-1 addWaiter()方法
         *        如果当前线程尝试获取【同步状态（锁）】失败（即，tryAcquire()方法返回 false），则
         *        构造 Node 结点（Node.Exclusive 独占式），并将当前线程安全的（CAS）加入到【同步队列/入口等待队列】的【尾部】。
         *        这里说的【同步队列】其实就是当前线程获取锁失败后加入的【阻塞队列】，也可以理解为【入口等待队列】。
         *     2-2 acquireQueued()方法
         *        以【独占模式、不间断（自旋）】获取已在【同步队列】中的线程。
         *        当前线程会根据公平性原则来进行阻塞等待（自旋），直到获取到锁为止；并返回当前线程在等待过程中有木有被中断过（即，返回中断标志）。
         *     2-3 selfInterrupt()方法
         *        产生一个中断。
         *     【综述】：当线程获取同步状态失败时，则会将当前线程构造为 Node 结点加入到（同步队列/阻塞队列/入口等待队列） 队列的尾部，
         *              然后通过【自旋】的方式不断获取同步状态，但是，在自旋的过程中需要判断当前线程是否需要阻塞。
         * </pre>
         */
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    /**
     * Acquires in exclusive mode, aborting if interrupted.
     * Implemented by first checking interrupt status, then invoking
     * at least once {@link #tryAcquire}, returning on
     * success.  Otherwise the thread is queued, possibly repeatedly
     * blocking and unblocking, invoking {@link #tryAcquire}
     * until success or the thread is interrupted.  This method can be
     * used to implement method {@link Lock#lockInterruptibly}.
     *
     * 1). 以【独占模式】、【阻塞式】获取同步状态。
     * 2). 该方法支持响应中断。
     *     该方法在等待获取同步状态时，如果当前线程被中断了，会立即响应中断并抛出 InterruptedException 异常。
     * {@link #acquire(int)}
     *
     * @param arg the acquire argument.  This value is conveyed to
     *            {@link #tryAcquire} but is otherwise uninterpreted and
     *            can represent anything you like.
     * @throws InterruptedException if the current thread is interrupted
     */
    public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        // 尝试【非阻塞式】、【独占模式】获取同步状态
        if (!tryAcquire(arg))
            // 如果【尝试】获取同步状态失败，则以【独占模式】、【不间断】获取已在【同步队列/阻塞队列/入口等待队列】中的线程。
            doAcquireInterruptibly(arg);
    }

    /**
     * Attempts to acquire in exclusive mode, aborting if interrupted,
     * and failing if the given timeout elapses.  Implemented by first
     * checking interrupt status, then invoking at least once {@link
     * #tryAcquire}, returning on success.  Otherwise, the thread is
     * queued, possibly repeatedly blocking and unblocking, invoking
     * {@link #tryAcquire} until success or the thread is interrupted
     * or the timeout elapses.  This method can be used to implement
     * method {@link Lock#tryLock(long, TimeUnit)}.
     *
     * 【独占模式】、超时限制 获取 【同步状态 state】
     *
     * @param arg          the acquire argument.  This value is conveyed to
     *                     {@link #tryAcquire} but is otherwise uninterpreted and
     *                     can represent anything you like.
     * @param nanosTimeout the maximum number of nanoseconds to wait
     * @return {@code true} if acquired; {@code false} if timed out
     * @throws InterruptedException if the current thread is interrupted
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();

        /**
         * 1- 先以 【独占模式】、【非阻塞式（CAS 的方式）】 尝试获取同步状态，调用 AQS 的实现类方法（自定义同步器各自实现）;
         * 2- 如果尝试获取同步状态失败的话，再去执行 {@link #doAcquireNanos(int, long)} 方法，
         *    以 【独占模式】、【阻塞式】 并 超时限制的方式获取同步状态。
         */
        return tryAcquire(arg) ||
                doAcquireNanos(arg, nanosTimeout);
    }

    /**
     * Releases in exclusive mode（以独占模式释放锁[同步状态]）.  Implemented by unblocking one or
     * more threads if {@link #tryRelease} returns true.
     * This method can be used to implement method {@link Lock#unlock}.
     *
     * @param arg the release argument.  This value is conveyed to
     *            {@link #tryRelease} but is otherwise uninterpreted and
     *            can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        // 1- 调用 AQS 实现类（自定义同步器）重写的 tryRelease 方法【尝试】【释放同步状态】
        if (tryRelease(arg)) {
            // 释放【同步状态】成功
            // 2-1 获取头结点
            Node h = head;
            // 2-1 如果 头结点不为空，且 waitStatus 不是初始状态
            /**
             * 在【独占模式 获取同步状态】的过程中，会把 waitStatus 的值从 初始状态0 更新成 signal 状态。
             * {@link #shouldParkAfterFailedAcquire(Node, Node)}
             * {@link #acquireQueued(Node, int)}
             */
            if (h != null && h.waitStatus != 0)
                // 解除线程挂起状态（即，唤醒【入口等待队列】中头结点的后继结点）
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    /**
     * Acquires in shared mode, ignoring interrupts.  Implemented by
     * first invoking at least once {@link #tryAcquireShared},
     * returning on success.  Otherwise the thread is queued, possibly
     * repeatedly blocking and unblocking, invoking {@link
     * #tryAcquireShared} until success.
     *
     * 以【共享模式】获取，忽略中断。首先调用至少一次 tryAcquireShared()【共享模式、非阻塞式 获取同步状态】，
     * 如果获取成功则返回。否则，线程将会排队，可能会重复阻塞和取消阻塞，调用 tryAcquireShared() 直至成功。
     *
     * 与 {@link #acquire(int)} 的区别在于：同一时刻可以有多个线程获取到同步状态（共享锁）。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *            {@link #tryAcquireShared} but is otherwise uninterpreted
     *            and can represent anything you like.
     */
    public final void acquireShared(int arg) {
        // 1- 调用 AQS 实现类（自定义同步器）重写的 tryAcquireShared() 方法，以【共享模式】、【非阻塞式】获取同步状态。
        //    如果返回结果小于 0，则说明获取同步状态失败。
        if (tryAcquireShared(arg) < 0)
            // 2- 调用 AQS 提供的模板方法
            //    ① 将当前线程安全的（CAS）加入到【同步队列/入口等待队列】的【尾部】。
            //    ② 以【共享模式、不间断】获取已在【同步队列】中的线程。
            doAcquireShared(arg);
    }

    /**
     * Acquires in shared mode, aborting if interrupted.  Implemented
     * by first checking interrupt status, then invoking at least once
     * {@link #tryAcquireShared}, returning on success.  Otherwise the
     * thread is queued, possibly repeatedly blocking and unblocking,
     * invoking {@link #tryAcquireShared} until success or the thread
     * is interrupted.
     *
     * @param arg the acquire argument.
     *            This value is conveyed to {@link #tryAcquireShared} but is
     *            otherwise uninterpreted and can represent anything
     *            you like.
     * @throws InterruptedException if the current thread is interrupted
     */
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        // 如果检测到中断标识为 true（interrupted()方法会重置中断标识），则抛出 InterruptedException
        if (Thread.interrupted())
            throw new InterruptedException();
        /**
         * 1- 调用【一次】自定义同步器（AQS 实现类）的 tryAcquireShared() 方法【共享模式、非阻塞式】获取同步状态。
         *    1). 如果该方法的返回值【大于等于 0】，则说明获取同步状态（锁）成功。详细说明请移步至 {@link #tryAcquireShared(int)}
         */
        if (tryAcquireShared(arg) < 0)
            // 2). 如果返回值 小于 0（即，获取同步状态失败），那就自旋去吧。
            doAcquireSharedInterruptibly(arg);
    }

    /**
     * Attempts to acquire in shared mode, aborting if interrupted, and
     * failing if the given timeout elapses.  Implemented by first
     * checking interrupt status, then invoking at least once {@link
     * #tryAcquireShared}, returning on success.  Otherwise, the
     * thread is queued, possibly repeatedly blocking and unblocking,
     * invoking {@link #tryAcquireShared} until success or the thread
     * is interrupted or the timeout elapses.
     *
     * @param arg          the acquire argument.  This value is conveyed to
     *                     {@link #tryAcquireShared} but is otherwise uninterpreted
     *                     and can represent anything you like.
     * @param nanosTimeout the maximum number of nanoseconds to wait
     * @return {@code true} if acquired; {@code false} if timed out
     * @throws InterruptedException if the current thread is interrupted
     */
    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquireShared(arg) >= 0 ||
                doAcquireSharedNanos(arg, nanosTimeout);
    }

    /**
     * Releases in shared mode（共享锁的释放）.  Implemented by unblocking one or more
     * threads if {@link #tryReleaseShared} returns true.
     *
     * @param arg the release argument.  This value is conveyed to
     *            {@link #tryReleaseShared} but is otherwise uninterpreted
     *            and can represent anything you like.
     * @return the value returned from {@link #tryReleaseShared}
     */
    public final boolean releaseShared(int arg) {
        // 1- 调用 自定义同步器（AQS 的实现类）的 tryReleaseShared() 方法释放同步状态。
        if (tryReleaseShared(arg)) {
            // 如果【完全】释放成功（即，同步状态 state == 0 为真），则唤醒下一个调用了【await()】方法而被阻塞的线程。
            doReleaseShared();
            return true;
        }
        return false;
    }

    // Queue inspection methods

    /**
     * Queries whether any threads are waiting to acquire. Note that
     * because cancellations due to interrupts and timeouts may occur
     * at any time, a {@code true} return does not guarantee that any
     * other thread will ever acquire.
     *
     * <p>In this implementation, this operation returns in
     * constant time.
     *
     * @return {@code true} if there may be other threads waiting to acquire
     */
    public final boolean hasQueuedThreads() {
        return head != tail;
    }

    /**
     * Queries whether any threads have ever contended to acquire this
     * synchronizer; that is if an acquire method has ever blocked.
     *
     * <p>In this implementation, this operation returns in
     * constant time.
     *
     * @return {@code true} if there has ever been contention
     */
    public final boolean hasContended() {
        return head != null;
    }

    /**
     * Returns the first (longest-waiting) thread in the queue, or
     * {@code null} if no threads are currently queued.
     *
     * <p>In this implementation, this operation normally returns in
     * constant time, but may iterate upon contention if other threads are
     * concurrently modifying the queue.
     *
     * @return the first (longest-waiting) thread in the queue, or
     * {@code null} if no threads are currently queued
     */
    public final Thread getFirstQueuedThread() {
        // handle only fast path, else relay
        return (head == tail) ? null : fullGetFirstQueuedThread();
    }

    /**
     * Version of getFirstQueuedThread called when fastpath fails
     */
    private Thread fullGetFirstQueuedThread() {
        /*
         * The first node is normally head.next. Try to get its
         * thread field, ensuring consistent reads: If thread
         * field is nulled out or s.prev is no longer head, then
         * some other thread(s) concurrently performed setHead in
         * between some of our reads. We try this twice before
         * resorting to traversal.
         */
        Node h, s;
        Thread st;
        if (((h = head) != null && (s = h.next) != null &&
                s.prev == head && (st = s.thread) != null) ||
                ((h = head) != null && (s = h.next) != null &&
                        s.prev == head && (st = s.thread) != null))
            return st;

        /*
         * Head's next field might not have been set yet, or may have
         * been unset after setHead. So we must check to see if tail
         * is actually first node. If not, we continue on, safely
         * traversing from tail back to head to find first,
         * guaranteeing termination.
         */

        Node t = tail;
        Thread firstThread = null;
        while (t != null && t != head) {
            Thread tt = t.thread;
            if (tt != null)
                firstThread = tt;
            t = t.prev;
        }
        return firstThread;
    }

    /**
     * Returns true if the given thread is currently queued.
     *
     * <p>This implementation traverses the queue to determine
     * presence of the given thread.
     *
     * @param thread the thread
     * @return {@code true} if the given thread is on the queue
     * @throws NullPointerException if the thread is null
     */
    public final boolean isQueued(Thread thread) {
        if (thread == null)
            throw new NullPointerException();
        for (Node p = tail; p != null; p = p.prev)
            if (p.thread == thread)
                return true;
        return false;
    }

    /**
     * Returns {@code true} if the apparent first queued thread, if one
     * exists, is waiting in exclusive mode.  If this method returns
     * {@code true}, and the current thread is attempting to acquire in
     * shared mode (that is, this method is invoked from {@link
     * #tryAcquireShared}) then it is guaranteed that the current thread
     * is not the first queued thread.  Used only as a heuristic in
     * ReentrantReadWriteLock.
     */
    final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        return (h = head) != null &&
                (s = h.next) != null &&
                !s.isShared() &&
                s.thread != null;
    }

    /**
     * Queries whether any threads have been waiting to acquire longer
     * than the current thread.
     *
     * <p>An invocation of this method is equivalent to (but may be
     * more efficient than):
     * <pre> {@code
     * getFirstQueuedThread() != Thread.currentThread() &&
     * hasQueuedThreads()}</pre>
     *
     * <p>Note that because cancellations due to interrupts and
     * timeouts may occur at any time, a {@code true} return does not
     * guarantee that some other thread will acquire before the current
     * thread.  Likewise, it is possible for another thread to win a
     * race to enqueue after this method has returned {@code false},
     * due to the queue being empty.
     *
     * <p>This method is designed to be used by a fair synchronizer to
     * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.
     * Such a synchronizer's {@link #tryAcquire} method should return
     * {@code false}, and its {@link #tryAcquireShared} method should
     * return a negative value, if this method returns {@code true}
     * (unless this is a reentrant acquire).  For example, the {@code
     * tryAcquire} method for a fair, reentrant, exclusive mode
     * synchronizer might look like this:
     *
     * <pre> {@code
     * protected boolean tryAcquire(int arg) {
     *   if (isHeldExclusively()) {
     *     // A reentrant acquire; increment hold count
     *     return true;
     *   } else if (hasQueuedPredecessors()) {
     *     return false;
     *   } else {
     *     // try to acquire normally
     *   }
     * }}</pre>
     *
     * @return {@code true} if there is a queued thread preceding the
     * current thread, and {@code false} if the current thread
     * is at the head of the queue or the queue is empty
     * @since 1.7
     *
     * <pre>
     * 1).返回
     *      判断当前线程是否有前序节点。如果有返回true，否则返回false。
     *    这句话的意思等同于
     *      判断当前线程是否位于 同步队列（入口等待队列） 中的第一个节点（即，当前线程是不是首个等待获取同步状态的线程节点）。
     *  如果是则返回 false（代表当前线程拥有获取同步状态的资格），否则返回 true。
     * 2).该方法的目的
     *      用来判断当前线程是否有抢占同步状态的资格。
     *      在公平锁中，由于 线程抢占同步状态 需要 排队，这个方法就是用来控制线程排队的。
     * </pre>
     */
    public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        /**
         * 1.返回 false 的情况
         *   1). h != t（头节点 != 尾节点） 为 false, 则说明同步队列为空（h == t 为真，只能说明他俩都没有被赋值，或者他俩指向的都是头节点）;
         *   2). h != t 为 true，但是 ((s = h.next) == null || s.thread != Thread.currentThread()) 为 false。
         *       ((s = h.next) == null || s.thread != Thread.currentThread()) 为 false 等价于
         *       ((s = h.next) != null && s.thread == Thread.currentThread()) 为 true，
         *       意味着头节点的后继节点（也就是第一个节点）不为空，且它的 thread 就是当前线程（即，当前线程是同步队列的第一个节点）。
         *   综上所述，当 同步队列为空 或者 当前线程是同步队列中的第一个线程节点时，返回 false。
         * 2.返回 true 的情况
         *   这个判断分了两大部分（以 && 作为分割），因为是【&&且】的关系，所以，只有当两部分同时为 true 时，结果才为true。
         *   1). h != t 为 true，说明同步队列不为空（也就是说同步队列中至少有两个节点，一个是 头节点，其他的就是 线程节点）。
         *   2). 只有当 h != t 为 true 时，才会继续判断后面的条件是否为真（也就是说，如果 h != t 为 false，那也就没必要继续后面的判断了）。
         *          ((s = h.next) == null || s.thread != Thread.currentThread()) 的结果想要是 true，
         *          只需要有一个条件成立即可，因为他俩是【||或】的关系。
         *     ①. (s = h.next) == null 为 true。
         *         Q: 上面说 h != t，那么怎么会存在 h.next 为 null 的情况呢？
         *         A: 只有可能是还没来得及给 head.next 赋值。从 {@link #enq(Node)} 同步队列入队的方法可以看出（else分支），
         *            一个线程节点的插入同步队列尾部操作是这样的：先给线程节点的prev赋值，再将其设置为尾节点，最后才会给原本的尾节点的next赋值。
         *     ②. (s = h.next) == null 为 false，但是 s.thread != Thread.currentThread() 为 true。
         *         说明头节点的后继节点（第一个节点）的thread 不是 当前线程。
         *   综上所述，正常情况下，我们是可以忽略①的情况的。一般情况下，当前线程 不是 头节点的后继节点的线程 时，返回 true。
         */
        return h != t &&
                ((s = h.next) == null || s.thread != Thread.currentThread());
    }


    // Instrumentation and monitoring methods

    /**
     * Returns an estimate of the number of threads waiting to
     * acquire.  The value is only an estimate because the number of
     * threads may change dynamically while this method traverses
     * internal data structures.  This method is designed for use in
     * monitoring system state, not for synchronization
     * control.
     *
     * @return the estimated number of threads waiting to acquire
     */
    public final int getQueueLength() {
        int n = 0;
        for (Node p = tail; p != null; p = p.prev) {
            if (p.thread != null)
                ++n;
        }
        return n;
    }

    /**
     * Returns a collection containing threads that may be waiting to
     * acquire.  Because the actual set of threads may change
     * dynamically while constructing this result, the returned
     * collection is only a best-effort estimate.  The elements of the
     * returned collection are in no particular order.  This method is
     * designed to facilitate construction of subclasses that provide
     * more extensive monitoring facilities.
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            Thread t = p.thread;
            if (t != null)
                list.add(t);
        }
        return list;
    }

    /**
     * Returns a collection containing threads that may be waiting to
     * acquire in exclusive mode. This has the same properties
     * as {@link #getQueuedThreads} except that it only returns
     * those threads waiting due to an exclusive acquire.
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getExclusiveQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            if (!p.isShared()) {
                Thread t = p.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

    /**
     * Returns a collection containing threads that may be waiting to
     * acquire in shared mode. This has the same properties
     * as {@link #getQueuedThreads} except that it only returns
     * those threads waiting due to a shared acquire.
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getSharedQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            if (p.isShared()) {
                Thread t = p.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

    /**
     * Returns a string identifying this synchronizer, as well as its state.
     * The state, in brackets, includes the String {@code "State ="}
     * followed by the current value of {@link #getState}, and either
     * {@code "nonempty"} or {@code "empty"} depending on whether the
     * queue is empty.
     *
     * @return a string identifying this synchronizer, as well as its state
     */
    public String toString() {
        int s = getState();
        String q = hasQueuedThreads() ? "non" : "";
        return super.toString() +
                "[State = " + s + ", " + q + "empty queue]";
    }


    // Internal support methods for Conditions

    /**
     * Returns true if a node, always one that was initially placed on
     * a condition queue, is now waiting to reacquire on sync queue.
     * 判断node节点是否在【入口等待队列】上，如果是，则返回true。
     *
     * @param node the node
     * @return true if is reacquiring
     */
    final boolean isOnSyncQueue(Node node) {
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        /**
         *      后继结点next不为 null，则该节点肯定在【入口等待队列/同步队列】上，
         *  因为 一个节点 插入 入口等待队列，先设置的是 前驱节点prev，再设置的是 后继节点next（这段逻辑参见{@link #enq(Node)}方法）。
         *      【条件等待队列】上的节点是单链表，而且节点之间是通过 {@link Node#nextWaiter} 相互连接的。
         *  而【入口等待队列】是双向链表，节点之间是通过 前驱节点prev 和 后继节点next 相互连接的。
         */
        if (node.next != null) // If has successor, it must be on queue
            return true;
        /*
         * node.prev can be non-null, but not yet on queue because
         * the CAS to place it on queue can fail. So we have to
         * traverse from tail to make sure it actually made it.  It
         * will always be near the tail in calls to this method, and
         * unless the CAS failed (which is unlikely), it will be
         * there, so we hardly ever traverse much.
         */
        return findNodeFromTail(node);
    }

    /**
     * Returns true if node is on sync queue by searching backwards from tail.
     * 在 同步队列（入口等待队列） 上，从【尾部开始向前】查找入参node，如果找到了就返回true。
     * Called only when needed by isOnSyncQueue.
     *
     * @return true if present
     */
    private boolean findNodeFromTail(Node node) {
        Node t = tail;
        for (; ; ) {
            if (t == node)
                return true;
            if (t == null)
                return false;
            t = t.prev;
        }
    }

    /**
     * Transfers a node from a condition queue onto sync queue.
     * 将【条件等待队列】中的 线程结点 移动到【同步队列/入口等待队列】中。
     * Returns true if successful.
     * 如果成功，则返回 true。
     *
     * @param node the node
     * @return true if successfully transferred (else the node was
     * cancelled before signal)
     */
    final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         * 如果不能改变结点的 waitStatus（等待状态），则表明该结点已经被取消了。
         */
        // 将该节点的状态从 condition 转换为 0
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

        /*
         * Splice onto queue and try to set waitStatus of predecessor to
         * indicate that thread is (probably) waiting. If cancelled or
         * attempt to set waitStatus fails, wake up to resync (in which
         * case the waitStatus can be transiently and harmlessly wrong).
         */
        // 将【条件等待队列】上的当前节点 node 移动到【锁的等待队列（即，线程的同步队列/入口等待队列/阻塞队列]）】中，即，入队操作。
        Node p = enq(node);
        // p 为 node 结点的前驱结点。
        int ws = p.waitStatus;
        /**
         * 如果 node 结点的前驱结点的状态为 cancelled（取消）
         * 或者
         * node 结点的前驱结点 设置 waitStatus 失败
         * 则，直接唤醒 node 结点的线程。
         */
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            // 唤醒【同步队列/入口等待队列/阻塞队列】中 node 结点的线程。
            LockSupport.unpark(node.thread);
        return true;
    }

    /**
     * Transfers node, if necessary, to sync queue after a cancelled wait.
     * 如果有必要，在取消等待后，将【条件等待队列】中的 node 结点移动到【同步队列/入口等待队列/阻塞队列】中。
     * Returns true if thread was cancelled before being signalled.
     *
     * @param node the node
     * @return true if cancelled before the node was signalled
     */
    final boolean transferAfterCancelledWait(Node node) {
        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
            enq(node);
            return true;
        }
        /*
         * If we lost out to a signal(), then we can't proceed
         * until it finishes its enq().  Cancelling during an
         * incomplete transfer is both rare and transient, so just
         * spin.
         */
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

    /**
     * Invokes release with current state value; returns saved state.
     * Cancels node and throws exception on failure.
     *
     * @param node the condition node for this wait
     * @return previous sync state
     *
     * 释放同步状态（锁资源），并返回该线程释放锁之前的同步状态值。
     */
    final int fullyRelease(Node node) {
        boolean failed = true;
        try {
            int savedState = getState();
            // 释放 同步状态（锁资源）
            if (release(savedState)) {
                failed = false;
                // 如果释放成功，则返回该线程释放锁之前的同步状态值。
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

    // Instrumentation methods for conditions

    /**
     * Queries whether the given ConditionObject
     * uses this synchronizer as its lock.
     *
     * @param condition the condition
     * @return {@code true} if owned
     * @throws NullPointerException if the condition is null
     */
    public final boolean owns(ConditionObject condition) {
        return condition.isOwnedBy(this);
    }

    /**
     * Queries whether any threads are waiting on the given condition
     * associated with this synchronizer. Note that because timeouts
     * and interrupts may occur at any time, a {@code true} return
     * does not guarantee that a future {@code signal} will awaken
     * any threads.  This method is designed primarily for use in
     * monitoring of the system state.
     *
     * @param condition the condition
     * @return {@code true} if there are any waiting threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *                                      is not held
     * @throws IllegalArgumentException     if the given condition is
     *                                      not associated with this synchronizer
     * @throws NullPointerException         if the condition is null
     */
    public final boolean hasWaiters(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.hasWaiters();
    }

    /**
     * Returns an estimate of the number of threads waiting on the
     * given condition associated with this synchronizer. Note that
     * because timeouts and interrupts may occur at any time, the
     * estimate serves only as an upper bound on the actual number of
     * waiters.  This method is designed for use in monitoring of the
     * system state, not for synchronization control.
     *
     * @param condition the condition
     * @return the estimated number of waiting threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *                                      is not held
     * @throws IllegalArgumentException     if the given condition is
     *                                      not associated with this synchronizer
     * @throws NullPointerException         if the condition is null
     */
    public final int getWaitQueueLength(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitQueueLength();
    }

    /**
     * Returns a collection containing those threads that may be
     * waiting on the given condition associated with this
     * synchronizer.  Because the actual set of threads may change
     * dynamically while constructing this result, the returned
     * collection is only a best-effort estimate. The elements of the
     * returned collection are in no particular order.
     *
     * @param condition the condition
     * @return the collection of threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *                                      is not held
     * @throws IllegalArgumentException     if the given condition is
     *                                      not associated with this synchronizer
     * @throws NullPointerException         if the condition is null
     */
    public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitingThreads();
    }

    /**
     * Condition implementation for a {@link
     * AbstractQueuedSynchronizer} serving as the basis of a {@link
     * Lock} implementation.
     *
     * <p>Method documentation for this class describes mechanics,
     * not behavioral specifications from the point of view of Lock
     * and Condition users. Exported versions of this class will in
     * general need to be accompanied by documentation describing
     * condition semantics that rely on those of the associated
     * {@code AbstractQueuedSynchronizer}.
     *
     * <p>This class is Serializable, but all fields are transient,
     * so deserialized conditions have no waiters.
     *
     * 这个类常用的两个方法是: await()、signal()。这两个方法的功能类比 {@link Object#wait()} 和 {@link Object#notify()}。
     */
    public class ConditionObject implements Condition, java.io.Serializable {
        private static final long serialVersionUID = 1173984872572414699L;
        /**
         * First node of condition queue.
         * 条件等待队列中的第一个结点
         */
        private transient Node firstWaiter;
        /**
         * Last node of condition queue.
         * 条件等待队列的最后一个结点
         */
        private transient Node lastWaiter;

        /**
         * Creates a new {@code ConditionObject} instance.
         */
        public ConditionObject() {
        }

        // Internal methods

        /**
         * Adds a new waiter to wait queue.
         * 添加新的 waiter 到【条件等待队列】。
         *
         * <pre>
         * 【注意】：
         *     ① 在 独占模式、阻塞式 获取同步状态 {@link AbstractQueuedSynchronizer#acquire(int)} 下，
         *        当尝试获取同步状态失败时，是 将当前线程加入到了【同步队列（即，也可理解为阻塞队列）】中，也就是说
         *        这个【同步队列】中存放的是获取同步状态失败的线程，对应方法为
         *        {@link AbstractQueuedSynchronizer#addWaiter(java.util.concurrent.locks.AbstractQueuedSynchronizer.Node)}
         *     ② 这里的不是【同步队列】，而是【条件等待队列】。
         *        当前线程在执行到临界区内部时（即，当前线程已经获取到了同步状态[锁]），当要求的条件不满足时就会进入到【条件等待队列】。
         * 举栗子：最经典的【生产者/消费者】模式。
         *         1). 描述：生产者去生产螺丝，然后放到池子中；消费者从池子中去取螺丝进行消费。
         *                   假设池子的大小为 10（也就是说在某一时刻最多只能容纳 10 个螺丝）。
         *         2). 执行方式：生产者和消费者同时进行。
         *         3). 生产者和消费者能够正常执行的条件
         *             ① 生产者往池子中放螺丝的条件就是：池子没有放满（即，池子中当前的螺丝数量小于 10）；
         *             ② 消费者从池子中消费螺丝的条件就是：池子中没有螺丝了（即，池子中当前的螺丝数量为 0）。
         *         4). 那么，问题来了。分两种情况来进行说明。
         *             ① 假设生产者生产螺丝的速度远远超过消费者消费螺丝的速度。那么，在这种情况下，池子很容易就会满了。
         *                当池子满的时候，生产者无法继续生产螺丝（即，生产者往池子中放螺丝的条件无法满足），此时，
         *                就需要一个【条件等待队列】来存放生产者线程。
         *             ② 假设消费者消费螺丝的速度远远超过生产者生产螺丝的速度。那么，同样的道理，池子中很容易就没有螺丝。
         *                当池子中没有螺丝的时候，消费者就无法继续进行消费动作（即，消费者从池子中消费螺丝的条件无法满足），
         *                此时，需要一个【条件等待队列】来存放消费者线程。
         * </pre>
         *
         * @return its new wait node
         */
        private Node addConditionWaiter() {
            // 将尾结点引用赋给局部变量t。
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            // 1- Node 结点的状态如果不为 condition，则表示该结点不处于【等待状态】，需要清除该结点。因为【条件等待队列】上的节点状态只会是condition。
            if (t != null && t.waitStatus != Node.CONDITION) {
                // 清除【条件等待队列】中所有状态不为 condition 的结点。
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            // 2- 为当前线程构建一个新的 Node 结点
            // （这里的 waitStatus 为 condition，而不是 0 或者 signal，这是要与【入口等待队列】中结点的状态区别开来）。
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            // 3- 构建【单向】条件等待队列（条件等待队列是一个单链表）。
            //    将该结点加入到【条件等待队列】的尾部。
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }

        /**
         * Removes and transfers nodes until hit non-cancelled one or
         * null. Split out from signal in part to encourage compilers
         * to inline the case of no waiters.
         *
         * 唤醒【条件等待队列】中的第一个节点。
         *
         * @param first (non-null) the first node on condition queue
         */
        private void doSignal(Node first) {
            do {
                /**
                 * 修改头结点，完成旧头结点的移出工作。
                 *  ① 将 first.nextWaiter 赋给 firstWaiter;
                 *  ② 将 first.nextWaiter 置为 null。
                 * 这样 first节点 就处于 游离状态了，也就是将 first节点 从 条件等待队列中 成功删除。
                 */
                if ((firstWaiter = first.nextWaiter) == null)
                    // 如果新的头结点为 null，则说明【条件等待队列】中没有结点元素了。
                    lastWaiter = null;
                // 将旧头节点的 nextWaiter 置为 null，方便 GC。
                first.nextWaiter = null;
                /**
                 * <pre>
                 *      调用transferForSignal()方法，将【条件等待队列】中的 线程节点 移动到
                 *  【锁的等待队列（即，线程的同步队列/入口等待队列/阻塞队列）】。
                 *      当 线程节点 移动到 同步队列后，当前线程再使用 LockSupport 唤醒该节点的线程。
                 *      线程被唤醒后，将从 await()方法中的 while 循环中退出（isOnSyncQueue(Node)方法返回true，因为节点已经在同步队列中了），
                 *  进而调用同步器的 acquireQueued()方法加入到获取同步状态的竞争中。【具体参见{@link #await()}】。
                 * </pre>
                 */
            } while (!transferForSignal(first) &&
                    (first = firstWaiter) != null);
        }

        /**
         * Removes and transfers all nodes.
         *
         * @param first (non-null) the first node on condition queue
         *              条件等待队列的第一个节点不为null。
         */
        private void doSignalAll(Node first) {
            lastWaiter = firstWaiter = null;
            do {
                Node next = first.nextWaiter;
                first.nextWaiter = null;
                transferForSignal(first);
                first = next;
            } while (first != null);
        }

        /**
         * Unlinks cancelled waiter nodes from condition queue.
         * Called only while holding lock. This is called when
         * cancellation occurred during condition wait, and upon
         * insertion of a new waiter when lastWaiter is seen to have
         * been cancelled. This method is needed to avoid garbage
         * retention in the absence of signals. So even though it may
         * require a full traversal, it comes into play only when
         * timeouts or cancellations occur in the absence of
         * signals. It traverses all nodes rather than stopping at a
         * particular target to unlink all pointers to garbage nodes
         * without requiring many re-traversals during cancellation
         * storms.
         *
         * 清除【条件等待队列】中所有状态不为 condition 的结点。
         *
         * Node 结点的状态如果不为 condition，则表示该结点不处于【等待状态】。
         */
        private void unlinkCancelledWaiters() {
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                // 如果t的waitStatus不是condition，说明这个节点不应该在【条件等待队列】上，那就把它删掉。
                if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    if (trail == null)
                        firstWaiter = next;
                    else
                        trail.nextWaiter = next;
                    if (next == null)
                        lastWaiter = trail;
                } else
                    trail = t;
                t = next;
            }
        }

        // public methods

        /**
         * Moves the longest-waiting thread, if one exists, from the
         * wait queue for this condition to the wait queue for the
         * owning lock.
         *
         * 唤醒：将等待时间最长的线程（如果存在的话）从【条件等待队列】移动到
         *      【锁的等待队列（即，线程的同步队列[或叫入口等待队列，或叫阻塞队列]）】。
         * 阻塞：{@link #await()}
         * 该方法的功能类似 {@link Object#notify()}。
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *                                      returns {@code false}
         */
        public final void signal() {
            // 判断当前线程是否拥有锁（正所谓“解铃还须系铃人”，我的锁怎么能让别人来解呢）
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                // 若 条件等待队列 不为空，则唤醒【条件等待队列】中的第一个节点。
                doSignal(first);
        }

        /**
         * Moves all threads from the wait queue for this condition to
         * the wait queue for the owning lock.
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *                                      returns {@code false}
         */
        public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignalAll(first);
        }

        /**
         * Implements uninterruptible condition wait.
         * <ol>
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         * throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled. 阻止，直到发出信号。
         * <li> Reacquire by invoking specialized version of
         * {@link #acquire} with saved state as argument.
         * </ol>
         */
        public final void awaitUninterruptibly() {
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean interrupted = false;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                // 代码走到这一行，说明当前线程已经被唤醒或者被中断。
                if (Thread.interrupted())
                    /**
                     * 如果线程被中断，则仅仅只是记录了一下中断标识。
                     * 并不像{@link #await()}方法一样，通过 break 跳出 while 循环，从而具有抢占锁资源的资格。
                     * 这里也说明了 awaitUninterruptibly()方法将线程阻塞后，只能通过 signal()来唤醒线程，从而具有抢占锁资源的资格。
                     */
                    interrupted = true;
            }
            if (acquireQueued(node, savedState) || interrupted)
                selfInterrupt();
        }

        /*
         * For interruptible waits, we need to track whether to throw
         * InterruptedException, if interrupted while blocked on
         * condition, versus reinterrupt current thread, if
         * interrupted while blocked waiting to re-acquire.
         */

        /**
         * Mode meaning to reinterrupt on exit from wait
         */
        private static final int REINTERRUPT = 1;
        /**
         * Mode meaning to throw InterruptedException on exit from wait
         */
        private static final int THROW_IE = -1;

        /**
         * Checks for interrupt, returning THROW_IE if interrupted
         * before signalled, REINTERRUPT if after signalled, or
         * 0 if not interrupted.
         * 判断 线程处于【条件等待队列】上时，是否被中断。
         * <pre>
         * 1).如果没有被中断，则返回0。
         * 2).如果被中断了，则继续判断是在唤醒之前被中断的还是唤醒后被中断的。
         *    ① 如果是在发出信号之前（唤醒之前）被中断，则返回 throw_ie;
         *    ② 如果是在发出信号之后（唤醒之后）被中断，则返回 reinterrupt。
         *    这里的判断依据本质上就是 transferAfterCancelledWait()和 {@link #transferForSignal(Node)}
         * （由 {@link #doSignal(Node)} 唤醒方法 调用）去争抢看谁先设置 node.waitStatus 成功【通过CAS的方式设置】。
         *    如果是 transferAfterCancelledWait()先设置成功，那就说明是在 线程被唤醒之前中断的;
         *    如果是 transferForSignal()先设置成功，那就说明是在 线程被唤醒之后中断的。
         * </pre>
         * @return int
         */
        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                    (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                    0;
        }

        /**
         * Throws InterruptedException, reinterrupts current thread, or
         * does nothing, depending on mode.
         */
        private void reportInterruptAfterWait(int interruptMode)
                throws InterruptedException {
            // interruptMode == THROW_IE 为 true的情况只有一种：线程节点在【条件等待队列】上被中断，而且是在唤醒之前被中断。
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

        /**
         * Implements interruptible condition wait.
         * 实现可中断条件等待。
         *
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         *      如果当前线程被中断，则抛出 InterruptedException。
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         * throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled or interrupted.
         *      阻塞直到发出信号或被中断。
         * <li> Reacquire by invoking specialized version of
         * {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * </ol>
         *
         * @throws java.lang.InterruptedException
         *
         * ① 线程在调用了 await() 方法后执行挂起操作，直到线程等待的某个条件为真时才会被唤醒。
         *      线程在接收到信号或被中断之前一直处于等待状态。
         * ② 当调用了该方法后，当前线程会释放锁资源（同步状态）。
         * ③ 该方法的功能类似 {@link Object#wait()}。
         */
        public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            // 1- 构建 Node 结点，将当前线程加入到【条件等待队列】。
            Node node = addConditionWaiter();
            // 2- 释放当前线程持有的 同步状态state（锁）
            // 【注意】：这里返回了当前线程的同步状态（state 值）。也就是说在释放锁的时候，也记录了一下当前线程的同步状态，方便后面再次竞争锁的时候用到。
            int savedState = fullyRelease(node);
            int interruptMode = 0;

            /**
             * <pre>
             * 检查此结点的线程是否在【同步队列/入口等待队列/阻塞队列】上。
             *    如果不在，则说明该线程还不具备竞争锁的资格（也就是说，该线程组成的node结点依然在 条件等待队列上），
             * 则需要 继续等待，直到检测到此结点在同步队列上。
             * 【备注】：
             *      ① 从这里就可以看出，当前线程已经被阻塞（while 循环）了。
             *      ② 如果 isOnSyncQueue()方法在【第一次】执行时就返回true，那么，while循环体就不会执行，
             *        也就是说，线程不需要被挂起，线程状态继续保持为 RUNNABLE（运行状态）。
             *        Q1: isOnSyncQueue() 方法在什么情况下 在第一次执行时就会返回true？
             *        A1：signal()方法 先于 isOnSyncQueue()方法执行时，就会返回true。
             *           例如，线程A调用await()方法，在执行isOnSyncQueue()方法之前，
             *           线程B调用了signal()方法将线程A构成的结点从【条件等待队列】移动到【入口等待队列】上。
             *           线程A在执行isOnSyncQueue()方法时就会返回true。
             *           这样的设计 就避免了不必要的线程挂起和唤醒操作，减少了状态转换的开销。
             *
             * Q2：线程在什么情况下才具备竞争锁的资格呢？
             * A2：① 当前线程线程从【条件等待队列】移动到【入口等待队列/同步队列】时，就意味着该线程具备了竞争锁的资格。
             *      Q2-1：线程什么时候才会从【条件等待队列】移动到【入口等待队列/同步队列】呢？
             *      A2-1：线程被唤醒（{@link #signal()}）时，就会移动到【入口等待队列】上。
             *     ② 当前线程被中断时，也意味着该线程具备了竞争锁的资格。
             *
             * 退出while循环的条件：
             *      ①当前线程从【条件等待队列】移动到了【入口等待队列】（移动过程由{@link #signal()}完成，即，当前线程被其他线程通过 signal()方法唤醒），
             *        此时isOnSyncQueue(Node)方法就会返回true;
             *      ②当前线程被中断，则interruptMode必然不等于0，此时，通过break跳出while循环。
             * </pre>
             */
            while (!isOnSyncQueue(node)) {
                // 挂起当前线程，线程状态转换为 WAITING（等待状态）。
                LockSupport.park(this);
                /**
                 * 代码走到这一行，说明当前线程已经被唤醒或者被中断。通过方法 checkInterruptWhileWaiting(Node)就可以判断线程是否被中断。
                 * ① 如果没有被中断（即，线程被正常唤醒），则interruptMode为0，继续下一次while循环，那么，在下一次while循环的时候，
                 *    isOnSyncQueue(Node)方法的返回值必然为true（因为被唤醒的线程会从【条件等待队列】移动到【入口等待队列】，
                 *    在方法{@link #doSignal(Node)}中完成），从而退出while循环。
                 * ② 如果被中断，则interruptMode必然不等于0，那么就通过break跳出while循环。
                 */
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }

            // ========== 分水岭 ==========

            /**
             * 代码走到这一步，说明【条件等待队列】中的线程节点node被唤醒或被中断，也意味着已经具备了抢占锁资源的资格。
             * 5- 竞争同步状态（锁）
             *      当线程被唤醒/被中断时，以【独占模式、不间断（自旋）】获取同步状态（锁资源）。
             *      当前线程会根据公平性原则来进行阻塞等待（CAS自旋），直到获取到锁为止;
             *      并返回当前线程在抢占锁资源的过程中是否被中断过（即，返回中断标志）。
             * 【备注】：这个地方跟 {@link #acquire(int)}（以独占模式、阻塞式获取同步状态）的处理逻辑就一样了。
             */
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                /**
                 * interruptMode != 0，有两种可能：
                 *   ① node节点在【条件等待队列】上时，是被中断后从而具备了抢占锁资源的资格。
                 *   ② node节点在抢占锁资源的过程中被中断过。
                 */
                reportInterruptAfterWait(interruptMode);
        }

        /**
         * Implements timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         * throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.<br />
         *      阻塞，直到收到信号、中断或超时。
         * <li> Reacquire by invoking specialized version of
         * {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * </ol>
         */
        public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            // 构建 Node 结点，将当前线程加入到【条件等待队列】。
            Node node = addConditionWaiter();
            // 释放当前线程持有的 同步状态state（锁）
            // 【注意】：这里返回了当前线程的同步状态（state 值）。也就是说在释放锁的时候，也记录了一下当前线程的同步状态，方便后面再次竞争锁的时候用到。
            int savedState = fullyRelease(node);
            // 用 当前时间（纳秒）+ 超时时间（剩余等待时间） = 具体的截止时间点
            final long deadline = System.nanoTime() + nanosTimeout;
            int interruptMode = 0;
            /**
             * 退出while循环的条件：
             *  ① isOnSyncQueue(Node)方法返回true
             *      当前线程 从【条件等待队列】移动到了【入口等待队列】，也就是说，当前线程被其他线程通过 signal()/signalALL()方法唤醒了。
             *  ② break 跳出while循环
             */
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    transferAfterCancelledWait(node);
                    break;
                }
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                // 重置 剩余等待时间
                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return deadline - System.nanoTime();
        }

        /**
         * Implements absolute timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         * throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         * {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean awaitUntil(Date deadline)
                throws InterruptedException {
            long abstime = deadline.getTime();
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (System.currentTimeMillis() > abstime) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                LockSupport.parkUntil(this, abstime);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        /**
         * Implements timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         * throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         * {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean await(long time, TimeUnit unit)
                throws InterruptedException {
            long nanosTimeout = unit.toNanos(time);
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            final long deadline = System.nanoTime() + nanosTimeout;
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        //  support for instrumentation

        /**
         * Returns true if this condition was created by the given
         * synchronization object.
         *
         * @return {@code true} if owned
         */
        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

        /**
         * Queries whether any threads are waiting on this condition.
         * Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.
         *
         * @return {@code true} if there are any waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *                                      returns {@code false}
         */
        protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }

        /**
         * Returns an estimate of the number of threads waiting on
         * this condition.
         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.
         *
         * @return the estimated number of waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *                                      returns {@code false}
         */
        protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    ++n;
            }
            return n;
        }

        /**
         * Returns a collection containing those threads that may be
         * waiting on this Condition.
         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.
         *
         * @return the collection of threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *                                      returns {@code false}
         */
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION) {
                    Thread t = w.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
    }

    /**
     * Setup to support compareAndSet. We need to natively implement
     * this here: For the sake of permitting future enhancements, we
     * cannot explicitly subclass AtomicInteger, which would be
     * efficient and useful otherwise. So, as the lesser of evils, we
     * natively implement using hotspot intrinsics API. And while we
     * are at it, we do the same for other CASable fields (which could
     * otherwise be done with atomic field updaters).
     */
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long waitStatusOffset;
    private static final long nextOffset;

    static {
        try {
            stateOffset = unsafe.objectFieldOffset
                    (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            headOffset = unsafe.objectFieldOffset
                    (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset
                    (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
            waitStatusOffset = unsafe.objectFieldOffset
                    (Node.class.getDeclaredField("waitStatus"));
            nextOffset = unsafe.objectFieldOffset
                    (Node.class.getDeclaredField("next"));

        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    /**
     * CAS head field. Used only by enq.
     */
    private final boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

    /**
     * CAS tail field. Used only by enq.
     * 通过 CAS 的方式设置值。
     *
     * @param expect 期望值
     * @param update 要修改的新值
     */
    private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

    /**
     * CAS waitStatus field of a node.
     */
    private static final boolean compareAndSetWaitStatus(Node node,
                                                         int expect,
                                                         int update) {
        return unsafe.compareAndSwapInt(node, waitStatusOffset,
                expect, update);
    }

    /**
     * CAS next field of a node.
     */
    private static final boolean compareAndSetNext(Node node,
                                                   Node expect,
                                                   Node update) {
        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
    }
}
